首页 > 其他分享 >【DP】【分治】LeetCode 53. 最大子数组和

【DP】【分治】LeetCode 53. 最大子数组和

时间:2023-04-14 09:23:59浏览次数:49  
标签:nums int sum 53 dp 数组 LeetCode DP result

题目链接

[https://leetcode.cn/problems/maximum-subarray/description/](53. 最大子数组和 "https://leetcode.cn/problems/maximum-subarray/description/")

思路

分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律

在数组的动态规划问题中,一般 dp[i] 都是表示以 nums[i] 为结尾的状态;dp[i][j] 分别表示 以 nums1[i]nums2[j] 为结尾的状态,以此类推

表示状态

首先构思一下我们需要存储的信息,以此来确定 dp 数组的维数:

  • 下标
  • 最大和,即当前状态值

因为只有两项信息需要存储,所以可以使用一维数组。

我们用 \(dp[i]\) 表示表示以 \(nums[i]\) 结尾的连续子数组的最大和。

找状态转移方程

这里直接给出状态转移方程,因为我也不知道该怎么解释

\[dp[i] = \left\{ \begin{aligned} & nums[i] + dp[i - 1], & dp[i - 1] \leq 0, \\ & nums[i], & dp[i - 1] < 0. \end{aligned} \right. \]

边界处理

很容易知道 \(dp[0] = nums[0]\),并且 \(result = nums[0]\)

空间优化

因为 \(dp[i]\) 只和 \(dp[i-1]\) 有关,所以可以不断更新维护单变量 sum 求出最终结果。

代码

dp数组版

class Solution {
    public int maxSubArray(int[] nums) {
        int[] dp = new int[nums.length];
        int result = nums[0];

        dp[0] = nums[0];
        for(int i = 1; i < nums.length; i++){
            if(dp[i - 1] < 0){
                dp[i] = nums[i];
            }else{
                dp[i] = nums[i] + dp[i - 1];
            }

            result = Math.max(result, dp[i]);
        }

        return result;
    }
}

空间优化版

class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        int sum = nums[0];

        for(int i = 1; i < nums.length; i++){
            if(sum < 0){
                sum = nums[i];
            }else{
                sum = nums[i] + sum;
            }

            result = Math.max(result, sum);
        }

        return result;
    }
}

标签:nums,int,sum,53,dp,数组,LeetCode,DP,result
From: https://www.cnblogs.com/shixuanliu/p/17317241.html

相关文章

  • POJ 1753 Flip Game (高斯消元)
    题目地址:POJ1753第三次做这道题了。第一次是刚学搜索的时候做的,第二次是刚学状态压缩枚举的时候做的,这次是刚学高斯消元、、每次都做得很艰辛。。目测这题应该没了别的方法了吧。。。。。。这题除了高斯消元外还需要枚举变元,方法是状态压缩枚举,然后返回去迭代解方程。代码如下:#inc......
  • Codeforces Round #286 (Div. 2) C题 Mr. Kitayuta, the Treasure Hunter (DFS+记忆化D
    题目地址:http://codeforces.com/contest/505/problem/C从d点开始,每个点都有三个方向,形成了一棵树,那么就从跟结点开始进行dfs查找,dp数组记录当前的点和长度,当这两个条件相同的时候,显然,后面的子树是完全相同的,于是用记忆化来优化。代码如下:#include<iostream>#include<string.h>#......
  • HDU 2089 不要62 (数位DP)
    简单的数位DP。代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm>#include<stdlib.h>#include<map>#include<set>#include<stdio.h>usingnamespacestd;#d......
  • 剑指 Offer 09. 用两个栈实现队列 && leetcode225.用队列实现栈
     剑指Offer09.用两个栈实现队列 classCQueue{private:stack<int>inStack,outStack;voidin2out(){//这里必须是while循环,如果是if判断,则输出栈日常只有一个值,没有起到先入后出的作用while(!inStack.empty()){//将输入栈栈顶......
  • leetcode:路径总和 III
    问题描述给定一个二叉树的根节点root ,和一个整数targetSum,求该二叉树里节点值之和等于targetSum的路径的数目。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。示例1输入:root=[10,5,-3,3,2,null,11,3,-2,null,1],ta......
  • HDU 4628 Pieces (状压DP)
    题目地址:HDU4628这题没想到怎么快速枚举子状态。。。看了题解才知道的。用for(state=i;state>0;state=(state-1)&i)就可以了。这题的具体做法是先预处理出所有的状态是不是回文串,然后就是普通的DP了。代码如下:#include<iostream>#include<string.h>#include<math.h>......
  • Codeforces Round #311 (Div. 2) E. Ann and Half-Palindrome (DP+字典树)
    题目地址:传送门先用dp求出所有的符合要求的半回文串,标记出来。然后构造字典树。然后再dfs一遍求出所有节点的子树和,最后搜一遍就能找出第k个来了。代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm>#include<stdlib......
  • POJ 1753 Flip Game(bfs枚举+递推)
    题目地址:http://poj.org/problem?id=1753这题此前曾经做过,但当时是用的纯BFS做的,然后后来又做了一次组队赛,那是16*16的,果断超时超内存。。能超的都超了。。于是又找了个更好的方法,就是枚举第一行,然后后面的根据第一行的情况推下去。比如,你要让所有的都变成W,如果上一行的对应位置是B......
  • codeforces#FF DIV2C题DZY Loves Sequences(DP)
    题目地址:http://codeforces.com/contest/447/problem/CC.DZYLovesSequencestimelimitpertestmemorylimitpertestinputoutputa,consistingof nai, ai + 1, .........
  • 力扣:153. 寻找旋转排序数组中的最小值
    已知一个长度为n的数组,预先按照升序排列,经由1到n次旋转后,得到输入数组。例如,原数组nums=[0,1,2,4,5,6,7]在变化后可能得到:若旋转4次,则可以得到[4,5,6,7,0,1,2]若旋转7次,则可以得到[0,1,2,4,5,6,7]注意,数组[a[0],a[1],a[2],...,a[n-1]]旋转一次的结果为数......