<数据结构与算法分析 C++描述>算法分析之最大子序列和问题

声明:这个系列博客是《数据结构与算法分析 C++描述》的读书笔记系列

参考博客:点击打开链接

本文是原书第二章内容,主要内容包括:算法的时间复杂度分析/算法的优化,分析的例子是很出名的最大子序列求和问题。

分为了四种方法来求解:穷举/穷举优化/递归(分治)/联机算法(动态规划), 算法复杂度为O(N^3)/O(N^2)/O(N*logN)/O(N). 思路都在具体代码里

----------------------------------------代码如下-------------------------------------------------------------------

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/*
 *计算并返回最大子序列和:穷举遍历
 *算法复杂度:O(N^3)
 */
int maxSubSum1(const vector<int> & a)
{
	int maxSum=0;
	for(int i=0; i < a.size(); i++) {
		for(int j=i; j < a.size(); j++) {
			int thisSum = 0;
			for(int k=i; k <= j; k++)
				thisSum += a[k];
			if(thisSum > maxSum)
				maxSum = thisSum;
		}
	}
	return maxSum;
}
/*
 * 同样是穷举,对上面的穷举进行了优化
 * 算法复杂度:O(N^2)
 */
int maxSubSum2(const vector<int> &a)
{
	int maxSum = 0;
	for(int i = 0; i < a.size(); i++) {
		int thisSum = 0;
		for(int j=i; j < a.size(); j++) {
			thisSum += a[j];
			if(thisSum > maxSum)
				maxSum = thisSum;
		}
	}
	return maxSum;
}

/*
 *使用递归的思路,将序列分为左右以及中间三大部分,其中左右部分可以用递归解决,
 *而中间部分是前半部分(包含左半部分最后一个元素)的最大值和右半部分(包含右半部分的第一个值)的最大值的和
 *将这三个值做比较就是最终的结果
 *算法复杂度:O(N*logN)
 */
int maxSubSum3(const vector<int> &a, int left, int right)
{
	if( left == right) {
		if( a[left] > 0)
			return a[left];
		else
			return 0;
	}

	int center = (left + right)/2;
	int maxLeftSum = maxSubSum3(a, left, center);
	int maxRightSum = maxSubSum3(a, center+1, right);
	int maxLeftAndRight = max(maxLeftSum, maxRightSum);

	int maxLeftBorderSum = 0, leftBorderSum = 0;
	for(int i = center; i >= left; i--) {
		leftBorderSum += a[i];
		if( leftBorderSum > maxLeftBorderSum)
			maxLeftBorderSum = leftBorderSum;
	}

	int maxRightBorderSum = 0, rightBorderSum = 0;
	for(int i = center+1; i <= right; i++) {
		rightBorderSum += a[i];
		if( rightBorderSum > maxRightBorderSum)
			maxRightBorderSum = rightBorderSum;
	}

	return max(maxLeftAndRight, maxLeftBorderSum + maxRightBorderSum);
}
/*
 * 动态规划,联机算法(on-line algorithm)
 * 联机算法:在任意时刻,算法对要操作的数据只读入(扫描)一次,一旦被读入并处理,它就不需要在被记忆了。而在此处理过程中算法能对它已经读入的数据立即给出相应子序列问题的正确答案。具有这种特性的算法叫做联机算法(on-line algorithm)。
 * 算法复杂度:O(N)
 */
int maxSubSum4(const vector<int> &a)
{
	int maxSum=0;
	int thisSum=0;
	for(int i=0; i<a.size(); i++) {
		thisSum += a[i];
		if(thisSum > maxSum)
			maxSum = thisSum;
		else if(thisSum < 0)
			thisSum = 0;
	}
	return maxSum;
}

int main()
{
	int input[] = {4,-3,5,-2,-1,2,6,-2};
	int length = sizeof(input)/4;
	//注意这里用数组去给vector容器初始化赋值的时候,区间是[begin,end)
	vector<int> inputVector(&input[0], &input[length]);

	//int result = maxSubSum3(inputVector, 0 , inputVector.size()-1);
	int result = maxSubSum4(inputVector);
	cout << "the maxSubSum is " << result << endl;
	return 0;
}

//test
//input[8] = {4,-3,5,-2,-1,2,6,-2};
时间: 2024-10-13 13:24:03

<数据结构与算法分析 C++描述>算法分析之最大子序列和问题的相关文章

《数据结构算法分析C描述》引论:选择问题,字谜游戏问题

#include <stdio.h> #include <stdlib.h> // 第一题 // 找出N个数的第k个最大者 // 方法1:排序(冒泡),降序找出第k个值 // 方法2:选前k个点进行降序排序,后面的数进行比较, // 如果数比第k个数小则忽略, 复杂度低于方法1 #define TYPE int #define TESTBUBLESORT 1 #define TESTBLOCKCOMPARE 1 #define TESTWORDPUZZLE 1 int findk_

数据结构与算法C++描述学习笔记1、辗转相除——欧几里得算法

前面学了一个星期的C++,以前阅读C++代码有些困难,现在好一些了.做了一些NOI的题目,这也是一个长期的目标中的一环.做到动态规划的相关题目时发现很多问题思考不通透,所以开始系统学习.学习的第一本是<数据结构与算法C++描述>第三版,边学边做一些笔记.所以这些笔记中的代码有很多将会非常简单,甚至可能只有一个记录或者结论. 辗转相除法用来求两个整数的最大公约数,即能同时整除两个数的最大整数.程序如下: int gdc(int m,int n){ int rem; while(n!=0){ //

数据结构与算法javascript描述

<数据结构与算法javascript描述>--数组篇 导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性,索引可能是整数.然而,这些数字索引在内部被转换为字符串类型,这是因为 JavaScript 对象中的属性名必须是字符串.在内部被归类为数组.由于 Array 在 JavaScript 中被当作对象,因此它有许多属性和方法可以在编程时使用. 使

数据结构与算法javascript描述笔记--数组篇

数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性,索引可能是整数.然而,这些数字索引在内部被转换为字符串类型,这是因为 JavaScript 对象中的属性名必须是字符串.在内部被归类为数组.由于 Array 在 JavaScript 中被当作对象,因此它有许多属性和方法可以在编程时使用. 使用数组: 1.创建数组 ① 使用 [] 操作符 ,var arr=[] ,该方法效率最高. ② 调用 Array 的构造函数创建数组,var myArr=new

翻阅《数据结构与算法javascript描述》--数组篇

导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性,索引可能是整数.然而,这些数字索引在内部被转换为字符串类型,这是因为 JavaScript 对象中的属性名必须是字符串.在内部被归类为数组.由于 Array 在 JavaScript 中被当作对象,因此它有许多属性和方法可以在编程时使用. 使用数组: 1.创建数组 使用 [] 操作符 ,var a

《数据结构与算法JavaScript描述》

<数据结构与算法JavaScript描述> 基本信息 作者: (美)Michael McMillan 译者: 王群锋 杜欢 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787115363398 上架时间:2014-8-5 出版日期:2014 年8月 开本:16开 版次:1-1 所属分类:计算机 > 软件与程序设计 > 网络编程 > javascript 更多关于>>> <数据结构与算法JavaScript描述> 编辑推荐 随着

数据结构(c语言描述)

数据结构(c语言描述) 目录 预备的数学知识 什么是数据结构 线性表 栈和队列 数组 串 树和二叉树 查找 排序 预备的数学知识 等差数列求和 Sn=(a1+an)*n/2 等比数列求和 Sn=a1*(1-q?)/(1-q) 什么是数据结构 基本概念 数据: 能够被计算机识别和处理的符号的集合 数据元素:是数据的基本单位,由若干的数据项构成,如一个人有手有脚 数据对象:由同类型的数据元素组成的集合,如一群人 数据类型:由一个集合和定义在此集合上的操作组成 原子类型:值不可再分的数据类型,如int

[数据结构与算法]常用排序算法分析与实现:第一部分

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289903.html 插入排序 直接插入排序.希尔排序 选择排序 简单选择排序.堆排序 交换排序 冒泡排序.快速排序 归并排序 基数排序 排序基类 1 package sort; 2 3 import java.util.Arrays; 4

javascript数据结构与算法--基本排序算法分析

javascript中的基本排序算法 对计算机中存储的数据执行的两种最常见操作是排序和检索,排序和检索算法对于前端开发尤其重要,对此我会对这两种算法做深入的研究,而不会和书上一样只是会贴代码而已,下面我会一步步从自己的理解的思路来一步步学习各个排序的思想.不过这些算法依赖于javascript中的数组来存储数据.最后我会来测试下基本算法(冒泡排序,选择排序,插入排序)的那个效率更高! 下面啊,我们先可以来封装常规数组操作的函数,比如:插入新数据,显示数组数据,还有交换数组元素等操作来调用不同的排