Given an integer array nums
, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
這道題讓求最大子數組之和,並且要用兩種方法來解,分別是 O(n) 的解法,還有用分治法 Divide and Conquer Approach,這個解法的時間復雜度是 O(nlgn),那就先來看 O(n) 的解法,定義兩個變量 res 和 curSum,其中 res 保存最終要返回的結果,即最大的子數組之和,curSum 初始值為0,每遍歷一個數字 num,比較 curSum + num 和 num 中的較大值存入 curSum,然后再把 res 和 curSum 中的較大值存入 res,以此類推直到遍歷完整個數組,可得到最大子數組的值存在 res 中,代碼如下:
C++ 解法一:
class Solution { public: int maxSubArray(vector<int>& nums) { int res = INT_MIN, curSum = 0; for (int num : nums) { curSum = max(curSum + num, num); res = max(res, curSum); } return res; } };
Java 解法一:
public class Solution { public int maxSubArray(int[] nums) { int res = Integer.MIN_VALUE, curSum = 0; for (int num : nums) { curSum = Math.max(curSum + num, num); res = Math.max(res, curSum); } return res; } }
題目還要求我們用分治法 Divide and Conquer Approach 來解,這個分治法的思想就類似於二分搜索法,需要把數組一分為二,分別找出左邊和右邊的最大子數組之和,然后還要從中間開始向左右分別掃描,求出的最大值分別和左右兩邊得出的最大值相比較取最大的那一個,代碼如下:
C++ 解法二:
class Solution { public: int maxSubArray(vector<int>& nums) { if (nums.empty()) return 0; return helper(nums, 0, (int)nums.size() - 1); } int helper(vector<int>& nums, int left, int right) { if (left >= right) return nums[left]; int mid = left + (right - left) / 2; int lmax = helper(nums, left, mid - 1); int rmax = helper(nums, mid + 1, right); int mmax = nums[mid], t = mmax; for (int i = mid - 1; i >= left; --i) { t += nums[i]; mmax = max(mmax, t); } t = mmax; for (int i = mid + 1; i <= right; ++i) { t += nums[i]; mmax = max(mmax, t); } return max(mmax, max(lmax, rmax)); } };
Java 解法二:
public class Solution { public int maxSubArray(int[] nums) { if (nums.length == 0) return 0; return helper(nums, 0, nums.length - 1); } public int helper(int[] nums, int left, int right) { if (left >= right) return nums[left]; int mid = left + (right - left) / 2; int lmax = helper(nums, left, mid - 1); int rmax = helper(nums, mid + 1, right); int mmax = nums[mid], t = mmax; for (int i = mid - 1; i >= left; --i) { t += nums[i]; mmax = Math.max(mmax, t); } t = mmax; for (int i = mid + 1; i <= right; ++i) { t += nums[i]; mmax = Math.max(mmax, t); } return Math.max(mmax, Math.max(lmax, rmax)); } }
Github 同步地址:
https://github.com/grandyang/leetcode/issues/53
類似題目:
Best Time to Buy and Sell Stock
Longest Turbulent Subarray
參考資料:
https://leetcode.com/problems/maximum-subarray/
https://leetcode.com/problems/maximum-subarray/discuss/20211/Accepted-O(n)-solution-in-java
https://leetcode.com/problems/maximum-subarray/discuss/20193/DP-solution-and-some-thoughts