Maximum Subarray
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.
题目要求
- 给定一个数组,求这个数组的连续子数组中的元素之和的最大值。
解题思路
有两种解决方法:1. 动态规划法 2. 分治法,这篇文章会分别介绍这两种方法并给出代码。
-
分治法:将原数组分成左右长度相同的两个子数组。由于是连续子数组,此时最大值只有可能有三种情况,在左边的子数组中,在右边的子数组中,横跨左右子数组;前两种情况可以通过递归求出来,第三种情况对左右子数组进行分析。因为是连续且横跨左右两个子数组,所以所以可以从中间开始分析,分别求出右边的最大连续子数组值和左边的连续子数组值,最后将这两者之和与前两种情况的结果相比较,取最大值。代码如下:
时间复杂度O(nlog n) 超过77%的java提交
class Solution { public int maxSubArray(int[] nums) { int l = 0,r = nums.length; return recursive(nums,l,r); } private int recursive(int[] nums,int l,int r){ if(l+1==r) return nums[l]; int middle = (l+r)/2; int lval = recursive(nums,l,middle); int rval = recursive(nums,middle,r); // 合并中间的值 int lspread=2,rspread=1,maxl = nums[middle-1],maxr=nums[middle]; int templ=maxl,tempr=maxr; while(middle-lspread>=l){ templ+=nums[middle-lspread]; maxl = Math.max(maxl,templ); lspread++; } while(middle+rspread<r){ tempr+=nums[middle+rspread]; maxr=Math.max(maxr,tempr); rspread++; } return Math.max(maxr+maxl,Math.max(lval,rval)); } }
- 动态规划法:超过100%的java提交
时间复杂度O(n)
class Solution { public int maxSubArray(int[] nums) { // 核心思想,如果当前计算的和小于0,那么肯定不可能使总的和更大了 // 所以此时我们重置当前计算的和 // 然后更新最大和 int maxsum=nums[0],tempsum = nums[0]; for(int i = 1;i<nums.length;i++){ tempsum = tempsum>0?tempsum+nums[i]:nums[i]; maxsum=maxsum>tempsum?maxsum:tempsum; } return maxsum; } }