问题描述:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
//贪心法
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 0 || nums == null) return 0;
int max = nums[0],sum = nums[0];
for(int i = 1; i < nums.length; ++i){
sum = Math.max(nums[i], sum + nums[i]);//当前最优和值
max = Math.max(max, sum);
}
return max;
}
}
//动态规划
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 0 || nums == null) return 0;
int max = nums[0];
for(int i = 1; i < nums.length; ++i){
if(nums[i-1] > 0) nums[i] += nums[i-1];//修改数组元素为当前位置最大和(不考虑后面元素)
max = Math.max(nums[i], max);//维护全局最大值
}
return max;
}
}
//分支算法
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 0 || nums == null) return 0;
return branch(nums, 0, nums.length - 1);
}
public int branch(int[] nums, int left, int right){//分治算法核心
if(left == right) return nums[left];
int mid = (left + right) / 2;//分支点
int leftSum = branch(nums, left, mid);//分支点左边最大子序和
int rightSum = branch(nums, mid+1, right);//分支点右边最大子序和
int crossSum = crossSum(nums, left, right, mid);//包含分支点的最大子序和
return Math.max(Math.max(leftSum, rightSum), crossSum);
}
public int crossSum(int[] nums, int left, int right, int mid){
if(left == right) return nums[left];
int leftSubSum = Integer.MIN_VALUE, curSum = 0;
for(int i = mid; i >= left; --i){//寻找分支点以左最大子序和
curSum += nums[i];
leftSubSum = Math.max(curSum, leftSubSum);
}
curSum = 0;
int rightSubSum = Integer.MIN_VALUE;
for(int i = mid+1; i <= right; ++i){//寻找分支点以右最大子序和(含分支点)
curSum += nums[i];
rightSubSum = Math.max(curSum, rightSubSum);
}
return leftSubSum + rightSubSum;
}
}