如果你对动态规划不熟悉,望转到该篇 \color{red}{如果你对动态规划不熟悉,望转到该篇~}如果你对动态规划不熟悉,望转到该篇
这道题很经典啦???????????? \color{green}{这道题很经典啦???? ???? ???? ~}这道题很经典啦????????????
什么题可以选择动态规划来做?
1.计数
- 有多少种方式走到右下角
- 有多少种方法选出k个数是的和是sum
2.求最大值最小值
- 从左上角走到右下角路径的最大数字和
- 最长上升子序列长度
3.求存在性
- 取石子游戏,先手是否必胜
- 能不能选出k个数使得和是sum
4.综合运用
- 动态规划 + hash
- 动态规划 + 递归
- ...
leecode 152. 乘积最大子数组
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
--
❤️❤️❤️❤️
2.1. 动态规划组成部分1:确定状态
简单的说,解动态规划的时候需要开一个数组,数组的每个元素f[i]或者f[i][j]代表什么,类似数学题中x, y, z代表什么
最后一步
这种题的话,我们可以定义一个最大值max为乘积最大子数组
因为涉及到负数,避免出现第一次负数,但第二次乘积是正数,我们还需要一个min为乘积最小子数组。
当然还需要一个变量,来记录乘积最大子数组ans
依次计算就行了。
1.2. 动态规划组成部分2:转移方程
简单的说:你需要记录
之前的乘积maxcurr,当前值curr和mincurr 的最大值
之前的乘积mincurr,当前值curr,和maxcurr 的最小值
1.3. 动态规划组成部分3:初始条件和边界情况
int max = nums[0], min = nums[0], ans = nums[0];
获取第一个值
1.4. 动态规划组成部分4:计算顺序
依次计算
坚持做对每一道中等题)???????????? \color{green}{坚持做对每一道中等题)???? ???? ???? ~}坚持做对每一道中等题)????????????
参考代码
GO语言版
func maxProduct(nums []int) int { maxF, minF, ans := nums[0], nums[0], nums[0] for i := 1; i < len(nums); i++ { mx, mn := maxF, minF maxF = max(mx * nums[i], max(nums[i], mn * nums[i])) minF = min(mn * nums[i], min(nums[i], mx * nums[i])) ans = max(maxF, ans) } return ans } func max(x, y int) int { if x > y { return x } return y } func min(x, y int) int { if x < y { return x } return y } 复制代码
NICE???????????? \color{red}{NICE???? ???? ???? ~}NICE????????????
java版
class Solution { public int maxProduct(int[] nums) { int maxF = nums[0], minF = nums[0], ans = nums[0]; int length = nums.length; for (int i = 1; i < length; ++i) { int mx = maxF, mn = minF; maxF = Math.max(mx * nums[i], Math.max(nums[i], mn * nums[i])); minF = Math.min(mn * nums[i], Math.min(nums[i], mx * nums[i])); ans = Math.max(maxF, ans); } return ans; } } 复制代码
❤️❤️❤️❤️