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个元素的最大和 就是他本身对吧?
动态规划的思维就是
- 划分子问题
- 结果复用
那我们来画图解释吧!
我们知道了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」 的比较, 如果大了, 就取最大的值,作为当前最大子序列的和, 并返回回去
讲到这里,就结束了, 最重要的是大家多实践, 不要单纯看完了就不做, 加油