Loading

最大子序和

1.问题描述

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

2.求解

错误的动态规划

  • 维护一个二维数组sum[i][j]表示从ij的和
  • 初始化对角线数组sum[i][i] = nums[i]
  • 对于sum[i][j] = sum[i][j - 1] + nums[j]

错误代码如下

public int maxSubArray(int[] nums) {
    int len = nums.length;
    int[][] sum = new int[len][len];
    int max = nums[0];
    for(int i = 0; i < len; i++){
        sum[i][i] = nums[i];
        if(nums[i] > max){
            max = nums[i];
        }
    }
    for(int i = 0; i < len - 1; i++){
        for(int j = i + 1;j < len; j++){
            sum[i][j] = sum[i][j - 1] + nums[j];
            if(sum[i][j] > max){
                max = sum[i][j];
            }
        }
    }
    return max;
}
  • 执行超时,没有必要记录所有的值

真正的动态规划

  • 对于nums[i]只有两种情况,自己独自成为一段或者加入之前i-1的一段
  • 如果我是nums[i],我肯定希望前面传给我一个正数,给我一个负数把我变小,那我不如只要自己
  • 使用变量pre来记录当前i-1的值,使用变量ans记录每次的最大值
  • 需要特别注意的是初始值,pre的初始值为0,但ans的初始值要设为数组的第一个数

代码如下

/*
 *执行用时:1 ms, 在所有 Java 提交中击败了95.83% 的用户
 * 内存消耗:38.3 MB, 在所有 Java 提交中击败了96.62% 的用户
 * */
public int maxSubArray(int[] nums) {
    int pre = 0,ans = nums[0];
    for(int x : nums){
        pre = Math.max(x,pre + x);
        ans = Math.max(ans,pre);
    }
    return ans;
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

分治算法

posted @ 2020-10-22 15:26  水纸杯  阅读(70)  评论(0)    收藏  举报