1. 程式人生 > >LeetCode53.最大子序和(C++實現)

LeetCode53.最大子序和(C++實現)

先上題目:

方法一: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),比較複雜,懶得寫了哈哈~