zoukankan      html  css  js  c++  java
  • 最大子序和

    问题描述

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

    示例:

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

    解法一(动态规划):

    用dp[i]表示第i位结尾的最大子数组的大小,那么当dp[i-1]小于0的时候,最大子数组就是dp[i]=nums[i],否则为dp[i]=dp[i-1]+nums[i],由于每个dp[i]只使用一次,我们可以只用一个dp变量来记录之前的子数组最大值,节省空间,过程中记录出现过最大值即可。

    思路分析

    采用动态规划,创建动态数组dp[],关键是要捋清楚dp[i]是啥,如何由之前的dp值来求当前的dp[i]?

    定义状态:dp[i]表示索引从0到i的元素组成的数组中最大子序和;
    初始状态:dp数组的第一个元素也就是数组的第一个元素本身,dp[0] = nums[0];
    状态转移方程:如果dp[i-1]大于0,那么很显然dp[i]的值就是在其基础上再加上一个nums[i];而当dp[i-1]小于0,那么dp[i-1]与nums[i]两者的和显然不如nums[i]本身的大,由于我们要连续数组最大和,所以直接抛弃这段就可以了,从当前元素nums[i]开始累计。
    因此,转移方程为:dp[i] = min{dp[i-1],0} + nums[i];
    根据dp[]的初始状态和转移方程,我们可以将dp[]数组填满,每个位置上的值代表着以这个位置元素结尾的最大连续子数组的最大和。因此,只需从dp[]中找到最大值即可。

    优化:由于每个dp[i]只使用一次,我们可以只用一个dp变量来记录之前的子数组最大值,节省空间,过程中记录出现过最大值即可

    class Solution {
        public int maxSubArray(int[] nums) {
            int max = nums[0], dp = nums[0];
            for (int i = 1; i < nums.length; i++) {
                if (dp <= 0) dp = nums[i];
                else dp += nums[i];
                max = Math.max(max, dp);
            }
            return max;
        }
    }

    总结:

    此题还可以用分支算法,实际上,分治法的复杂度并没有动态规划方法的复杂度好。

    分治法主要是递归的拆解数组为左右两部分,当拆解到一个元素时开始返回,并“组装”每两部分。

  • 相关阅读:
    Retrieve Excel Workbook Sheet Names
    总股本和流通股本
    Net序列化与数据压缩类
    HTTP Compression 速用方法
    市净率
    兼容FF,IE,Chrome的js离开或刷新页面检测
    【转】不能执行已释放的Script 代码
    三款在线css3样式生成工具
    不固定个数的子元素自适应居中
    收集几个浏览器好用插件工具
  • 原文地址:https://www.cnblogs.com/xiaofeng-fu/p/13941897.html
Copyright © 2011-2022 走看看