LeetCode53.最大子序和(C++實現)
阿新 • • 發佈:2018-12-12
先上題目:
方法一: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),比較複雜,懶得寫了哈哈~