LeetCode 53 - 最大子序和 - 解题思路记录(附带动态规划) - GoLang

548 阅读3分钟

Hello, 我又来了, 今天给大家带来一道Easy的题目,最大子序和,也可以从中牵扯出动态规划的思路,那么废话不多说,跟着我的思路走吧!

还是老样子先看题目

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

给定一个数组, 要求出这个数组的子数组中元素相加最大的和, 那么这道题目怎么解呢?
就是应用 动态规划(Dynamic Programming) 思路,我们来举个例子

现在数组中有9个数组, 那么我们怎么样知道这9个数字最大的和是什么?
不知道? 没关系, 那要是只有8个呢? 7个呢? 6个呢?....1个呢?

如果1个元素的最大和 就是他本身对吧?
动态规划的思维就是

  1. 划分子问题
  2. 结果复用

那我们来画图解释吧!

我们知道了arr[0]的最大和是-2
那我们推理的话,arr[1]的最大和就是arr[0]+arr[1], 但是这里需要考虑一个问题,arr[0]+arr[1]是不是最大

答案很明显 arr[0]+arr[1] = -1 所以arr[1]的最大和应该是他本身, 因为1 > -1
我们按照这样的思路,我们把接下来的9个数字全部推导出来, 会获得下面一个数组

会获得这么一个数字, dp中的每一个值, 都是dp[i-1]的最优解, 那么最优解就意味着选择, 那选与不选怎么参考? 动态规划做的就是这件事

比方我们要求F(3)的值,其实就是

这么一个公式 f(i) = max(f(i-1), 0) + f(i) 看不懂的没关系, 主要的的是多推导

那么到这里来说, 我们是不是一定要用一个数组去存着所有的子数组的和呢? 是不是有点浪费

我们似乎只需要保存上一个的最大和就行了对吧, 因为我们每一次的 f(i) 都是在跟 f(i-1) 做比较
那我为什么还要开一个数组呢? 浪费!

接下来,我们来看超简单版本的做法, 只需要用一个2个变量则可以做到此题, 上代码

func maxSubArray(nums []int) int {
	if len(nums) == 1{
		return nums[0]
	}
	max := nums[0]
	last := nums[0]
	for i:=1; i< len(nums); i++{
		last = Max(nums[i], last+nums[i])
		max = Max(last, max)
	}
	return max
}
func Max(x, y int) int{
	if x > y{
		return x
	}
	return y
}

一个方法Max用于求最大值, 这个没什么好说的

我们来看一下这两句重要的地方

last = Max(nums[i], last+nums[i])
max = Max(last, max)

当前f(i) 有没有比 last(上一个最大和)+f(i) 的值大, 如果有则说明当前 f(i) 是最大的和, 否则 **last+f(i)**才是

接下来, 我们需要更新最大子序列的和, 那么就是 last 跟 当前 max 的比较, 如果大了, 就取最大的值,作为当前最大子序列的和, 并返回回去

讲到这里,就结束了, 最重要的是大家多实践, 不要单纯看完了就不做, 加油

其他相关题目连接

LeetCode 49 - 字母异位词分组 - 解题思路记录 - Golang

LeetCode 21 - 合并有序链表 - 解题思路记录 - GoLang

LeetCode 2 - 两数之和 - 解题思路记录 - GoLang

LeetCode 12 - 罗马数字 - 解题思路记录 - GoLang

LeetCode 15 - 3数之和 - 解题思路记录 - GoLang

LeetCode 5 - 回文串 - 解题思路记录 - GoLang