編程之法:面試和算法心得(最大連續子數組和)
阿新 • • 發佈:2018-01-11
參考 否則 ++ 例子 返回 log 遍歷 方法 時間
內容全部來自編程之法:面試和算法心得一書,實現是自己寫的使用的是java
題目描述
輸入一個整形數組,數組裏有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。 求所有子數組的和的最大值,要求時間復雜度為O(n)。
例如輸入的數組為1, -2, 3, 10, -4, 7, 2, -5,和最大的子數組為3, 10, -4, 7, 2, 因此輸出為該子數組的和18。
分析與解法
解法一
求一個數組的最大子數組和,我想最直觀最野蠻的辦法便是,三個for循環三層遍歷,求出數組中每一個子數組的和,最終求出這些子數組的最大的一個值。 令currSum[i, …, j]為數組A中第i個元素到第j個元素的和(其中0 <= i <= j < n),maxSum為最終求到的最大連續子數組的和。
且當全是負數的情況時,我們可以讓程序返回0,也可以讓程序返回最大的那個負數,這裏,我們讓程序返回最大的那個負數。
參考代碼如下:
/* * 求一個數組的最大子數組和,我想最直觀最野蠻的辦法便是,三個for循環三層遍歷, * 求出數組中每一個子數組的和,最終求出這些子數組的最大的一個值。 * 令currSum[i, …, j]為數組A中第i個元素到第j個元素的和(其中0 <= i <= j < n), * maxSum為最終求到的最大連續子數組的和。 * 且當全是負數的情況時,我們可以讓程序返回0,也可以讓程序返回最大的那個負數,這裏,我們讓程序返回最大的那個負數。*/ public static int solution1(int[] arr) { int maxSum = arr[0]; for(int i=0;i<arr.length;i++) { for(int j=i;j<arr.length;j++) { int currSum = 0; for(int k=i;k<j;k++) { currSum+=arr[k]; } maxSum = Math.max(maxSum, currSum); } } return maxSum; }
此方法的時間復雜度為O(n^3)。
解法二
事實上,當我們令currSum為當前最大子數組的和,maxSum為最後要返回的最大子數組的和,當我們往後掃描時,
- 對第j+1個元素有兩種選擇:要麽放入前面找到的子數組,要麽做為新子數組的第一個元素;
- 如果currSum加上當前元素a[j]後不小於a[j],則令currSum加上a[j],否則currSum重新賦值,置為下一個元素,即currSum = a[j]。
- 同時,當currSum > maxSum,則更新maxSum = currSum,否則保持原值,不更新。
即
currSum = max(a[j], currSum + a[j])
maxSum = max(maxSum, currSum)
舉個例子,當輸入數組是1, -2, 3, 10, -4, 7, 2, -5,那麽,currSum和maxSum相應的變化為:
- currSum: 0 1 - 1 3 13 9 16 18 13
- maxSum : 0 1 1 3 13 13 16 18 18
參考代碼如下:
/* * 解法二 * 事實上,當我們令currSum為當前最大子數組的和,maxSum為最後要返回的最大子數組的和,當我們往後掃描時, * 對第j+1個元素有兩種選擇:要麽放入前面找到的子數組,要麽做為新子數組的第一個元素; * 如果currSum加上當前元素a[j]後不小於a[j],則令currSum加上a[j],否則currSum重新賦值,置為下一個元素,即currSum = a[j]。 * 同時,當currSum > maxSum,則更新maxSum = currSum,否則保持原值,不更新。 * 即 * currSum = max(a[j], currSum + a[j]) * maxSum = max(maxSum, currSum) */ public static int solution2(int[] arr) { int maxSum = arr[0]; int currSum = 0; for(int i=1;i<arr.length;i++) { currSum = Math.max(arr[i], currSum + arr[i]); maxSum = Math.max(maxSum, currSum); } return maxSum; }
編程之法:面試和算法心得(最大連續子數組和)