Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >《剑指offer》第26天:最大子序和

《剑指offer》第26天:最大子序和

作者头像
程序员小浩
发布于 2020-09-14 09:08:46
发布于 2020-09-14 09:08:46
34300
代码可运行
举报
文章被收录于专栏:小浩算法小浩算法
运行总次数:0
代码可运行

在上一篇文章011.动态规划系列 —第一讲(70)中,我们讲解了DP的概念并且通过示例了解了什么是动态规划。本篇中,我们将继续通过1道简单题型,进一步学习动态规划的思想。

01、题目分析

第53题:最大子序和

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

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6

拿到题目请不要直接看下方题解,先自行思考2-3分钟....

02、题目图解

首先我们分析题目,一个连续子数组一定要以一个数作为结尾,那么我们可以将状态定义成如下:

dp[i]:表示以 nums[i] 结尾的连续子数组的最大和。

那么为什么这么定义呢?因为这样定义其实是最容易想到的!在上一节中我们提到,状态转移方程其实是通过1-3个参数的方程来描述小规模问题和大规模问题间的关系。

当然,如果你没有想到,其实也非常正常!因为该问题最早于 1977 年提出,但是直到 1984 年才被发现了线性时间的最优解法。

根据状态的定义,我们继续进行分析:如果要得到 dp[i],那么 nums[i] 一定会被选取。并且 dp[i] 所表示的连续子序列与 dp[i-1] 所表示的连续子序列很可能就差一个 nums[i] 。即:

dp[i] = dp[i-1]+nums[i] , if (dp[i-1] >= 0)

但是这里我们遇到一个问题,很有可能 dp[i-1] 本身是一个负数。那这种情况的话,如果 dp[i] 通过 dp[i-1]+nums[i] 来推导,那么结果其实反而变小了,因为我们 dp[i] 要求的是最大和。所以在这种情况下,如果 dp[i-1] < 0,那么 dp[i] 其实就是 nums[i] 的值。即

dp[i] = nums[i] , if (dp[i-1] < 0)

综上分析,我们可以得到:

dp[i]=max(nums[i], dp[i−1]+nums[i])

得到了状态转移方程,但是我们还需要通过一个已有的状态的进行推导,我们可以想到 dp[0] 一定是以 nums[0] 进行结尾,所以

dp[i] = dp[i-1]+nums[i] , if (dp[i-1] >= 0)dp[0] = nums[0]

在很多题目中,因为 dp[i] 本身就定义成了题目中的问题,所以 dp[i] 最终就是要的答案。但是这里状态中的定义,并不是题目中要的问题,不能直接返回最后的一个状态 (这一步经常有初学者会摔跟头)。所以最终的答案,其实我们是寻找:

max(dp[0], dp[1], ..., d[i-1], dp[i])

分析完毕,我们绘制成图(图中假定 nums 为 [-2,1,-3,4,-1,2,1,-5,4]):

03、Go语言示例

根据以上分析,可以得到代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Go
func maxSubArray(nums []int) int {
 if len(nums) < 1 {
  return 0
 }
 dp := make([]int, len(nums))
    //设置初始化值 
 dp[0] = nums[0]
 for i := 1; i < len(nums); i++ {
        //处理 dp[i-1] < 0 的情况
  if dp[i-1] < 0 {
   dp[i] = nums[i]
  } else {
   dp[i] = dp[i-1] + nums[i]
  }
 }
 result := -1 << 31
 for _, k := range dp {
  result = max(result, k)
 }
 return result
}

func max(a, b int) int {
 if a > b {
  return a
 }
 return b
}

我们可以进一步精简代码为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Go
func maxSubArray(nums []int) int {
 if len(nums) < 1 {
  return 0
 }
    dp := make([]int, len(nums))
 result := nums[0]
    dp[0] = nums[0]
 for i := 1; i < len(nums); i++ {
  dp[i] = max(dp[i-1]+nums[i], nums[i])
  result = max(dp[i], result)
 }
 return result
}

func max(a, b int) int {
 if a > b {
  return a
 }
 return b
}

复杂度分析:时间复杂度:O(N)。空间复杂度:O(N)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小浩算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
53. 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
Michel_Rolle
2021/02/20
3.1K0
最大子序和
大家好,我是来自「华为」的「小熊」。端午假期马上就要结束了,小熊给大家带来一道笔试和面试中与「动态规划」相关的常考的简单题,这道题被字节、微软、亚马逊和苹果等各大互联网大厂作为笔试题。
程序员小熊
2021/06/21
2910
最大子序和
漫画:动态规划系列 第二讲
在上一篇文章中,我们讲解了DP的概念并且通过示例了解了什么是动态规划。本篇中,我们将继续通过1道简单题型,进一步学习动态规划的思想。
程序员小浩
2020/03/31
3380
动态规划入门看这篇就够了,万字长文!
今天是小浩算法 “365刷题计划” 动态规划 - 整合篇。大家应该期待已久了吧!奥利给!
程序员小浩
2020/05/08
1.7K0
动态规划入门看这篇就够了,万字长文!
​LeetCode刷题实战53:最大子序和
https://leetcode-cn.com/problems/maximum-subarray/
程序员小猿
2021/01/20
3260
干货:图解算法——动态规划系列
讲解动态规划的资料很多,官方的定义是指把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解。概念中的各阶段之间的关系,其实指的就是状态转移方程。很多人觉得DP难(下文统称动态规划为DP),根本原因是因为DP区别于一些固定形式的算法(比如DFS、二分法、KMP),没有实际的步骤规定第一步第二步来做什么,所以准确的说,DP其实是一种解决问题的思想。
宜信技术学院
2020/03/06
8360
Leetcode#53.Maximum Subarray(最大子序和)
题目描述 给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。 例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4], 连续子序列 [4,-1,2,1] 的和最大,为 6。 扩展练习: 若你已实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 思路 思路一: maxSum 必然是以numsi结尾的某段构成的,也就是说maxSum的candidate必然是以nums[i]结果的。如果遍历每个candidate,然后进行比较,那么就能找到最大的max
武培轩
2018/04/18
8490
LeetCode 0053. 最大子序和[动态规划详解]
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
Yano_nankai
2021/03/04
2970
LeetCode 0053. 最大子序和[动态规划详解]
Leetcode No.53 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
week
2022/01/07
3050
剑指Offer题解 - Day19
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
chuckQu
2022/08/19
1450
最大子序和,又贪心又DP
力扣题目链接:https://leetcode-cn.com/problems/maximum-subarray
代码随想录
2021/11/16
3510
图解LeetCode——53. 最大子数组和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
爪哇缪斯
2023/05/07
3021
图解LeetCode——53. 最大子数组和
Python 刷题笔记:一道简单级的动态规划题
今天翻看了关于时间复杂度、空间复杂度的文章和视频,对其认知加深了些,之后也要养成分析复杂度的习惯,顺手添加,大家如果看到我写错的还望予以纠正。
TTTEED
2020/07/08
1.2K0
动态规划:最大子序和
题目地址:https://leetcode-cn.com/problems/maximum-subarray/
代码随想录
2021/04/07
4450
动态规划:最大子序和
贪心算法:最大子序和
题目地址:https://leetcode-cn.com/problems/maximum-subarray/
代码随想录
2020/12/14
8810
贪心算法:最大子序和
LeetCode-53-最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
benym
2022/07/14
1830
画解算法:53. 最大子序和
https://leetcode-cn.com/problems/maximum-subarray/
灵魂画师牧码
2019/06/27
6100
画解算法:53. 最大子序和
leetcode题解-53.最大子序和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
编程珠玑
2019/09/02
5120
☆打卡算法☆LeetCode 53、最大子序和 算法解析
链接:53. 最大子序和 - 力扣(LeetCode) (leetcode-cn.com)
恬静的小魔龙
2022/08/07
3270
☆打卡算法☆LeetCode 53、最大子序和  算法解析
07— 最大子数组和【LeetCode 53】
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
吃猫的鱼Code
2023/07/24
2430
07— 最大子数组和【LeetCode 53】
相关推荐
53. 最大子序和
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验