[leetcode/lintcode 題解]阿里巴巴面試題:最大子陣列 II
阿新 • • 發佈:2020-12-29
技術標籤:演算法leetcodepythonjava資料結構
描述
給定一個整數陣列,找出兩個 不重疊 子陣列使得它們的和最大。
每個子陣列的數字在陣列中的位置應該是連續的。
返回最大的和。
線上評測地址:https://www.lintcode.com/problem/maximum-subarray-ii/?utm_source=sc-csdn-fks
樣例 1:
輸入:
[1, 3, -1, 2, -1, 2]
輸出:
7
解釋:
最大的子陣列為 [1, 3] 和 [2, -1, 2] 或者 [1, 3, -1, 2] 和 [2].
樣例2:
輸入: [5,4] 輸出: 9 解釋: 最大的子陣列為 [5] 和 [4].
挑戰
要求時間複雜度為 O(n)
解題思路
這題是最大子段和的升級版。我們只要在求最大子段和的基礎上,計算出前後綴的最大子段和,就可以列舉分界點來計算結果。
程式碼思路
對於字首的最大子段和,我們可以先求以i位置為結尾的最大子段和的值leftMax[i]。
max中的兩個引數分別代表延續前一個為結尾的最大欄位和,或者當前的nums[i]成為一段新的子段的兩種情況。
計算字首最大子段和prefixMax,計算字首最大值即可。
字尾的值也同理進行計算。
最後列舉分界點,取最大值,最終的結果為:
複雜度分析
設陣列長度為N。
-
只需常數次地遍歷陣列,時間複雜度為O(N)。
-
需要常數個額外陣列來記錄當前位置結尾前後綴最大連續和以及前後綴最大連續和,空間複雜度為O(N)。
public class Solution { /* * @param nums: A list of integers * @return: An integer denotes the sum of max two non-overlapping subarrays */ public int maxTwoSubArrays(List<Integer> nums) { int n = nums.size(); // 計算以i位置為結尾的前後綴最大連續和 List<Integer> leftMax = new ArrayList(nums); List<Integer> rightMax = new ArrayList(nums); for (int i = 1; i < n; i++) { leftMax.set(i, Math.max(nums.get(i), nums.get(i) + leftMax.get(i - 1))); } for (int i = n - 2; i >= 0; i--) { rightMax.set(i, Math.max(nums.get(i), nums.get(i) + rightMax.get(i + 1))); } // 計算前後綴部分的最大連續和 List<Integer> prefixMax = new ArrayList(leftMax); List<Integer> postfixMax = new ArrayList(rightMax); for (int i = 1; i < n; i++) { prefixMax.set(i, Math.max(prefixMax.get(i), prefixMax.get(i - 1))); } for (int i = n - 2; i >= 0; i--) { postfixMax.set(i, Math.max(postfixMax.get(i), postfixMax.get(i + 1))); } int result = Integer.MIN_VALUE; for (int i = 0; i < n - 1; i++) { result = Math.max(result, prefixMax.get(i) + postfixMax.get(i + 1)); } return result; } }
更多題解參考:https://www.lintcode.com/problem/maximum-subarray-ii/?utm_source=sc-csdn-fks