[LeetCode] 系统刷题5_Dynamic Programming

Dynamic Programming 实际上是[LeetCode] 系统刷题4_Binary Tree & Divide and Conquer的基础上,加上记忆化的过程。就是说,如果这个题目实际上是类似于Divide and conquer或者说是DFS,但是在计算过程中有很多重复计算同样的过程的话,那么就可以用Dynamic prgramming/记忆化搜索来完成。基本就是利用空间来简化时间复杂度的过程。

 

可以/很有可能使用Dynamic programming的条件,满足之一即可。

1. Maximum/Minimum

2. Yes/No. True/False

3. Count(*) 

 

一定不是Dynamic programming的条件,满足之一即可。

1. all 具体方案。

2. input是集合或者跟position无关。

3. move 4 directions in 二维数组。(或者说不是固定方向,有可能会有循环)

 

动态规划4要点:

1. 状态 state

mem[i][j] 代表什么,ex. 代表s1前i个characters和s2前j个characters。

2. Function

mem[i][j] = mem[i - 1][j] if ****

3. Initialize

usually mem[0][0]  / mem[i][0]/ mem[0][j]

4. 答案

mem[n]/mem[n - 1]/mem[m][n]

 

在这里将Dynamic programming分为几类。

1. 矩阵Dynamic programming/Matrix DP

state: mem[i][j] 走到坐标(x, y) 的状态。

[LeetCode] 120. Triangle _Medium tag: Dynamic Programming

[LeetCode] 64. Minimum Path Sum_Medium tag: Dynamic Programming

[LeetCode] 62. Unique Paths_ Medium tag: Dynamic Programming

[LeetCode] 63. Unique Paths II_ Medium tag: Dynamic Programming

 

2. Sequence DP

state: mem[i] 前i个位置

mem 的length 设为n

[LeetCode] 70. Climbing Stairs_ Easy tag: Dynamic Programming

[LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming

[LeetCode] 45. Jump Game II_ Hard tag: Dynamic Programming

 

3. 分割DP

state: mem[i] 前i个character 是否可行

mem 的length 设为n + 1,因为要考虑到前0个character,也就是empty string。

[LeetCode] 132. Palindrome Partitioning II_ Hard tag: Dynamic Programming

[LeetCode] 139. Word Break_ Medium tag: Dynamic Programming

 

4. Two sequences DP

state: mem[i][j] 表明s1的前i个characters, 配上s2的前j 个characters。

mem 的length 设为(n + 1)* (m + 1),因为要考虑到前0个character,也就是empty string。

需要初始化 mem[i][0], mem[0][j]

[LintCode] 77. Longest common subsequences_ Medium tag: Dynamic Programming

[LeetCode] 72. Edit Distance_hard tag: Dynamic Programming

[LeetCode] 115. Distinct Subsequences_ Hard tag: Dynamic Programming

[LeetCode] 97. Interleaving String_ Hard tag: Dynamic Programming

 

5. 背包 backpack DP

1) 经典 01 背包问题 (给nums为物品大小, size为target大小的背包, 要装尽量多的东西)

利用二维dp, dp[len(nums) + 1][target + 1]     , all False

# initial

dp[i][0] = True   , i = [0, n]

# function

dp[i][j] = dp[i - 1][j]         or      dp[i - 1][j - nums[i - 1]] if j >= nums[i - 1] else dp[i - 1][j]         # dp[i][j] 表示前i个物品中是否能组成size 为j的背包,如果可以为True, 否者为False

              不取当前物品           取当前物品

[LeetCode] 416. Partition Equal Subset Sum_Medium tag: backpack

 

2) 可选无数次的 01 背包问题(给nums为物品大小, size 为target大小的背包,要装尽量少的物品使得size == target)

利用二维dp, dp[len(nums) + 1][target + 1]     , all float('inf')

# initial

dp[i][0] = 0   , i = [0, n]

# function

dp[i][j] = min( dp[i - 1][j]         ,      dp[i][j - nums[i - 1]] + 1) if j >= nums[i - 1] else dp[i - 1][j]         # dp[i][j] 表示前i个物品中小于size 为j的背包的最大价值之和  

                     不取当前物品                      取当前物品                             # dp[i][j - nums[i - 1]] + 1 因为可以反复选同样的元素

return dp[n][target] if dp[n][target] < float('inf') else -1

 [LeetCode] 322. Coin Change_Medium tag: backpack

 

3) 可选一次的最大value sum背包问题(size array A, value array V and size of the backpack m)

跟单纯的01 背包其实很像, 利用二维dp, dp[len(A) + 1][target + 1]     , all 0

# function

dp[i][j] = max( dp[i - 1][j]         ,      dp[i - 1][j - A[i - 1]] + V[i - 1] ) if j >= A[i - 1] else dp[i - 1][j]         # dp[i][j] 表示前i个物品中小于size 为j的背包的最大价值之和

              不取当前物品                      取当前物品

return dp[n][m]

 

4) nums中选k个num, 使得sum == target.  可以求a.是否存在, 或者b.方案总数

利用三维数组, dp = [n + 1][k + 1][target + 1]

# initial

a. 是否存在

dp[i][0][0] = True, 其他False

b. 方案总数

dp[i][0][0] = 1, 其他 0

 

# function

a. 是否存在

dp[i][j][t] = dp[i - 1][j][t] or dp[i - 1][j - 1][t - nums[i - 1]] if t >= nums[i - 1] else dp[i - 1][j][t]

b. 方案总数

dp[i][j][t] = dp[i - 1][j][t] + dp[i - 1][j - 1][t - nums[i - 1]] if t >= nums[i - 1] else dp[i - 1][j][t]

 

# result

a. 是否存在

return dp[n][k][target]

b. 方案总数

return dp[n][k][target]

转载于:https://www.cnblogs.com/Johnsonxiong/p/10793639.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值