一 题目
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.
二 分析
EASY级别,这道题让求最大子数组之和,并且要用两种方法来解,分别是 O(n) 的解法,还有用分治法 Divide and Conquer Approach,先看O(n)的方法。定义两个变量 res 和 sum,其中 res 保存最终要返回的结果,即最大的子数组之和,sum 初始值为0.sum 从头向后遍历, 累加起来, 如果累加的结果小于0, 则退出循环,
public static int maxSubArray(int[] nums) {
//coner case
if(nums== null||nums.length==0 ){
return 0;
}
int res =nums[0];
int sum =0;
for(int i=0;i< nums.length;i++ ){
sum += nums[i];
res = Math.max(res, sum);
if(sum<0){
sum =0;
}
}
return res;
}
Runtime: 1 ms, faster than 85.43% of Java online submissions for Maximum Subarray.
Memory Usage: 41.9 MB, less than 5.16% of Java online submissions forMaximum Subarray.
时间复杂度:O(n)
分治法:
我们将数组均分为两个部分,那么最大子数组会存在于:左边和右边的最大子数组,从中间开始向左右分别扫描。
这里我没想出来,漏掉中间部分了,看了grandyang 大神的文章。实现起来还是比较啰嗦的。
假设数组下标有效范围是left到right,将数组分为左半部分下标为(left,mid-1)和右半部分下标为(mid+1,right)以及中间元素下标为mid,接下来递归求出左半部分的最大子序和:lmax=helper(nums,left,mid-1); 右半部分最大子序和rmax=helper(nums,mid+1,right);
接下来再将左半部分右边界,右半部分左边界以及中间元素nums[mid]整合,用了两个循环,先整合左半部分右边界和中间值,再将整合结果与右半部分左边界整合得到整合以后的最大子序和mmax,最后返回mmax,lmax,rmax 的最大值即是要求的最大子序和。代码如下:
private static int helper(int[] nums, int left, int right) {
if(left>=right){
return nums[left];
}
int mid = (left+right)/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));
}
Runtime: 2 ms, faster than 11.52% of Java online submissions for Maximum Subarray.
Memory Usage: 43.3 MB, less than 5.16% of Java online submissions forMaximum Subarray.
时间复杂度:O(nlogn) .
虽然比上面慢,而且写起来复杂。但是分治是个重要的算法。只是这里不那么合适。
参考: