53.最大子序和Leetcode

24 篇文章 0 订阅
3 篇文章 0 订阅

思路一:暴力求解(O(n^3))

class Solution {
    public int maxSubArray(int[] nums) {
        
        int maxSum = 0;
        
        for(int start = 0; start < nums.length; start++){//确定子序列的起点
            for(int end = start; end < nums.length; end++){//确定子序列的终点
                int thisSum = 0;
                for(int index = start; index <= end; index++){
                    thisSum = thisSum + nums[index];
                }
                if(thisSum > maxSum){
                    maxSum = thisSum;
                }
            }
        }
        return maxSum;
    }
}

思路二:暴力求解的改进(O(n^2))

class Solution {
    public int maxSubArray(int[] nums) {
        
        int maxSum = Integer.MIN_VALUE;
        
        for(int i = 0; i < nums.length; i++){//确定子序列的起点
        int thisSum = 0;
            for(int j = i; j < nums.length; j++){//确定子序列的终点
                thisSum += nums[j];
                if(thisSum > maxSum){
                    maxSum = thisSum;
                }
            }
        }
        return maxSum;
    }
}

这里需要注意的地方:

开始要定义maxSum = Integer.MIN_VALUE

原因是数列中有负数的存在

 

思路三:动态规划(大事化小,小事化了)

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

示例:

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

思路:首先要知道,这道题用动态规划的思路是从底到顶,由大化小。当数组只有一个数时,最大的那个就是他自己。这时,记sum[1] = -2。当有两个数时,因为sum[1] = -2,后面不管补上一个什么数,子序和都会减小。比如:用1加上 -2,子序和肯定是减小的。所以就要抛弃 -2,重新开始计数,从1开始。然后是 -3,因为 -3前面的子序和是正数,所以用 -3 加上1是会变大的。依次类推。

刚开始很疑惑不解的是当子序为-2, 1 , -3的时候,我是从左到右想的,sum[2] = 1,那么遇到 -3的时候加上sum[2]就变小了,所以不能要 -3。这么想是错的。因为万一序列是-2, 5 , -3, 10的话,虽然sum[2] = 5,加上 -3会变小,但是后面还有10,如果不要 -3,相当于从10开始计数,而5 + -3是一个整数,最大子序和不是10 ,而是5 , -3, 10。

所以,这道题的正确思路应该是这样的。如果sum[i]是正数,那么num[i+1]就接在sum[i]上;如果如果sum[i]是负数,那么就重新从num[i+1]开始记数。

就比如上边这个例子,sum[2] = 1,计算sum[3]的时候用-3 加上 1,这时可以看做以 -3 结尾的子序和变大了,后面的数加了有可能还会变大。

代码实现:

class Solution{
    public int maxSubArray(int[] nums){
        
        //用maxSum来记录当前最大的子序和
        int maxSum = Integer.MIN_VALUE;
        int[] sum = new int[nums.length];
        sum[0] = nums[0];
        maxSum = sum[0];
        
        for(int i = 1; i < nums.length; i++){
            if(sum[i-1] < 0){
                sum[i] = nums[i];
            }else if(sum[i-1] >= 0){
                sum[i] = sum[i-1] + nums[i];
            }
            
            if(sum[i] > maxSum){
                maxSum = sum[i];
            }
        }
        return maxSum;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值