题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
提示:
- $1 <= nums.length <= 10^5$
- $10^4 <= nums[i] <= 10^4$
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
题解
1、有条件的累加
sum > 0
则一直累加: sum += num
否则 sum = num
- 入参:一个数组
- 初始化最大子序和
- 初始化临时求和
- 遍历数组
- sum > 0
- 累加
- 否则 初始化为当前位置的数字值
- 更新最大字序和
- sum > 0
- 返回最大子序和
class Solution {
public int maxSubArray(int[] nums) {
// 求和,和为负数时,重置sum
int ans = nums[0];
int sum = 0;
for (int num : nums) {
if (sum > 0) {// 只要sum没有是负数,就继续求和
sum += num;
} else {
sum = num;
}
// 更新最大值
ans = Math.max(ans,sum);
}
return ans;
}
}
2、动态规划、贪心
class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length;
int currSum = nums[0], maxSum = nums[0];
for(int i = 1; i < n; ++i) {
currSum = Math.max(nums[i], currSum + nums[i]);// 等价于
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
}
}
// 链接:https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-by-leetcode/
// 原地算法,实现求和
class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length, maxSum = nums[0];
for(int i = 1; i < n; ++i) {
if (nums[i - 1] > 0) nums[i] += nums[i - 1];
maxSum = Math.max(nums[i], maxSum);
}
return maxSum;
}
}
3、分治法
类似二分的归并排序:
- 去二分值
- 二分左递归
- 二分右递归
- 左右合并,通过累加计算最优子序和,求解
- 对左边子序列和、右边子序和、合并子序和求最大值,并返回
class Solution {
public int crossSum(int[] nums, int left, int right, int p) {
if (left == right) return nums[left];
// 计算左侧
int leftSubsum = Integer.MIN_VALUE;
int currSum = 0;
for(int i = p; i > left - 1; --i) {
currSum += nums[i];
leftSubsum = Math.max(leftSubsum, currSum);
}
// 计算右侧
int rightSubsum = Integer.MIN_VALUE;
currSum = 0;
for(int i = p + 1; i < right + 1; ++i) {
currSum += nums[i];
rightSubsum = Math.max(rightSubsum, currSum);
}
// 返回两侧的和
return leftSubsum + rightSubsum;
}
// 二分递归
public int helper(int[] nums, int left, int right) {
if (left == right) return nums[left];
int p = (left + right) / 2;
int leftSum = helper(nums, left, p);
int rightSum = helper(nums, p + 1, right);
// 处理 left 到 right 内的最大连续和,中间值为p
int crossSum = crossSum(nums, left, right, p);
return Math.max(Math.max(leftSum, rightSum), crossSum);
}
public int maxSubArray(int[] nums) {
return helper(nums, 0, nums.length - 1);
}
}
// 链接:https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-by-leetcode/
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com