• LeetCode刷题--53. 最大子序和(简单)


    题目描述

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

    示例:

    输入: [-2,1,-3,4,-1,2,1,-5,4]

    输出: 6

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

    进阶:

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

    方法一:动态规划

    首先需要把这个问题分解成最优子问题来解。最主要的思路就是将上面的45个组合进行
    ,分解成数量较少的几个子问题。在这里我们一共有9个数字,顺理成章的我们把组合分解成9个小组的组合。

    第一个子组合是以第一个数字结尾的连续序列,也就是 [-2],最大值-2

    第二个子组合是以第二个数字结尾的连续序列,也就是 [-2,1], [1],最大值1

    第三个子组合是以第三个数字结尾的连续序列,也就是 [-2,1,3], [1,3], [3],最大值4

    以此类推。。。

    如果我们能够得到每一个子组合的最优解,也就是子序列的最大值,整体的最大值就可以通过比较这9个子组合的最大值来得到了。

    现在我们找到了最优子问题,重叠子问题在哪呢?那就得细心比较一下每个子问题。

    从第二个子组合和第三个子组合可以看到,组合 3 只是在组合 2 的基础上每一个数组后面添加第 3 个数字,也就是数字 3,然后增加一个只有第三个数字的数组 [3] 。

    这样两个组合之间的关系就出现了,可是我们不关心这个序列是怎么生成的,只是关心最大值之间的关系。

    • 下面我们看组合 3 的组成,我们将子组合 3 分成两种情况:
    1. 继承子组合二得到的序列,也就是[-2,1,3], [1,3] (最大值 1 = 第二个组合的最大值 + 第三个数字)
    2. 单独第三个数字的序列,也就是[3] (最大值 2 = 第三个数字)

    如果 第二个序列的最大值 大于0,那么最大值 1 就比最大值 2 要大,反之最大值 2 较大。

    这样,我们就通过第二个组合的最大值和第三个数字,就得到了第三个组合的最大值。因为第二个组合的结果被重复用到了,所以符合这个重叠子问题的定义。

    通俗来讲这个问题就变成了,第 i 个子组合的最大值可以通过第i-1个子组合的最大值和第 i 个数字获得,如果第 i-1 个子组合的最大值没法给第 i

    数字带来正增益,我们就抛弃掉前面的子组合,自己就是最大的了。

     代码实现

    class Solution {
        public int maxSubArray(int[] nums) {
            int len = nums.length;//数组长度
            //如果数组长度为0,直接返回0
            if (len == 0) {
                return 0;
            }
            int[] dp = new int[len];//创建一个数组dp,长度为 原数组的长度
            dp[0] = nums[0];//让元素组的第一个元素等于dp数组第一个元素
            for (int i = 1; i < len; i++) {
                //如果第 i-1 个子组合的最大值可以给第 i 个数字带来正增益,就两个组合相加。
                if (dp[i - 1] >= 0) {
                    dp[i] = dp[i - 1] + nums[i];
                //反之我们就抛弃掉前面的子组合,自己就是最大的了。
                } else {
                    dp[i] = nums[i];
                }
            }
            // 最后不要忘记全部遍历一遍,求最大值
            int ans = dp[0];
            for (int i = 1; i < len; i++) {
                ans = Math.max(ans, dp[i]);
            }
            return ran;
        }
    }
    • 状态压缩 , 来看看代码,我们只需要一个变量sum保存前面子组合的最大值,另外一个ans保存全局最大值。
    public int maxSubArray(int[] nums) {
        int ans = nums[0];
        int sum = 0;
        //动态规划的是首先对数组进行遍历,当前最大连续子序列和为 sum,结果为 ans
        for(int num: nums) {
            //如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字
            if(sum > 0) {
                sum += num;
                //如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字
            } else {
                sum = num;
            }
            //每次比较 sum 和 ans的大小,将最大值置为ans,遍历结束返回结果
            ans = Math.max(ans, sum);
        }
        return ans;
    }
  • 相关阅读:
    企业版证书打包APP发布,安装后闪退问题解决。
    Swift 与 Object-C 交互 (Swift版本为:1.2)
    iOS开发-代码片段(Code Snippets)提高开发效率
    iOS开发-Object-C可变参数函数
    MAC-Zsh安装与使用——终极Shell
    Git-学习笔记(常用命令集合)
    CSS动画,2D和3D模块
    CSS定位与布局
    CSS基础
    CSS概述
  • 原文地址:https://www.cnblogs.com/xiaozhongfeixiang/p/12489578.html
Copyright © 2020-2023  润新知