LeetCode53.最大子序和(C++实现)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28584889/article/details/83754712

先上题目:

方法一:O(N^3)暴力解法(会报超时)

//方法一:O(N^3)暴力解法(会报超时)
/*
O(N^3)的暴力解法比较容易想到,就是利用三层循环遍历计算每个可能的子序列,求其和并进行比较
但是因为时间复杂度太大,在LeetCode会报超时。
*/
int maxSubArray(vector<int>& nums) {
	int maxSum = nums[0];
	int tmpSum;
	for (int i = 0; i < nums.size(); i++) //子序列的左边起始点
	{
		for (int j = i; j < nums.size(); j++) //子序列的右边结束点
		{
			tmpSum = 0;
			for (int k = i; k <= j; k++) //计算每个子序列的和
			{
				tmpSum += nums[j];
			}
			if(tmpSum > maxSum)
				maxSum = tmpSum; //如有子序列的和更大的,则更换当前的最大子序列和
		}
	}
	return maxSum;
}

方法二:O(N^2)改进暴力解法

//方法二:O(N^2)改进暴力解法
/*
仔细观察上面的暴力解法,我们发现在第三层循环计算子序列的和的时候,每次都要重复计算之前计算过的
子序列和,所以所可以改进;其实就是可以把第三次循环扔掉,计算子序列和的时候每加一个元素就比较一次
因为时间复杂度有所下降,所以在LeetCode可以通过。
*/
int maxSubArray(vector<int>& nums) {
	int maxSum = nums[0];
	int tmpSum;
	for (int i = 0; i < nums.size(); i++)
	{
		tmpSum = 0;
		for (int j = i; j < nums.size(); j++)
		{
			tmpSum += nums[j];
			if(tmpSum > maxSum)
				maxSum = tmpSum;
		}
	}
	return maxSum;
}

方法三:O(N)扫描法(动态规划法)

//方法三:O(N)扫描法(动态规划法)
/*
该算法比较巧妙,只需一轮循环就可解决,线性复杂度。
具体思路就是:从第一个元素开始计算最大子序和,并且用tmpSum来记录当前的最大子序和,从头到尾遍历,
如果tmpSum为负,那么它就会拖低之后的子序和计算,所以应该重新定位当前的子序和temSum;如果tmpSum为
正,则加上当前的元素值。最后在每次的循环最后比较一下tmpSum和maxSum的值,如果tmpSum比maxSum大,则替换。
*/
int maxSubArray_second(vector<int>& nums) {
	int maxSum = nums[0];
	int tmpSum = nums[0];
	for (int i = 1; i < nums.size(); i++)
	{
		if(tmpSum < 0) //当前数小于0 肯定会舍去(否则将会影响接下来的和),换为下一个数
			tmpSum = nums[i];
		else  
			tmpSum += nums[i]; //如果当前数不小于0,那么他会对接下来的和有积极影响
		if(tmpSum > maxSum)
			maxSum = tmpSum; //这里既实现了负数返回最大也实现了扫描法
		 //这里其实已经隐式的列举了所有可能,保留了所有可能的最大值
	}
	return maxSum;
}

最后,还有一种分治法的,时间复杂度为O(NlogN),比较复杂,懒得写了哈哈~

猜你喜欢

转载自blog.csdn.net/qq_28584889/article/details/83754712
今日推荐