LeetCode第53题地址。
题目描述:
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
例子:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解题:动态规划
解析:主要找当前元素nums[i] 和其之前子串和比较大小,留下较大的元素。
class Solution{
public int maxSubArray(int[] nums) {
int pre = 0, res = nums[0];
for (int i = 0; i < nums.length; i++) {
pre = Math.max(pre + nums[i], nums[i]);
res = Math.max(res, pre);
}
return res;
}
}
复杂度
时间复杂度:O(n),其中n为nums数组的长度。我们只需要遍历一遍数组即可求得答案。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。
解题:分治法
连续子序列的最大和主要由这三部分子区间里元素的最大和得到:
第 1 部分:子区间 [left, mid];
第 2 部分:子区间 [mid + 1, right];
第 3 部分:包含子区间 [mid , mid + 1] 的子区间,即 nums[mid] 与 nums[mid + 1] 一定会被选取。
对它们三者求最大值即可。
class Solution {
public int maxSubArray(int[] nums) {
return maxSubArrayPart(nums, 0, nums.length-1);
}
public int maxSubArrayPart(int[] nums, int left, int right){
if (left == right) return nums[left];
int mid = (left+right)/2;
return Math.max(maxSubArrayPart(nums,left,mid),Math.max(maxSubArrayPart(nums,mid+1,right),maxSubArrayAll(nums,left,mid,right)));
}
public int maxSubArrayAll(int[] nums, int left, int mid, int right){
int leftSum = Integer.MIN_VALUE;
int sum = 0;
for (int i = mid; i >=left; i--){
sum+=nums[i];
leftSum = Math.max(sum,leftSum);
}
sum = 0;
int rightSum=Integer.MIN_VALUE;
for(int i = mid + 1; i <=right;i++){
sum+=nums[i];
rightSum = Math.max(rightSum, sum);
}
return leftSum+rightSum;
}
}
复杂度
时间复杂度:O(nlogn),这里递归的深度是对数级别的,每一层需要遍历一遍数组(或者数组的一半、四分之一)。
空间复杂度:O(1)。只需要常数空间存放若干变量。
thinking:
如何能沉下来分析解题??