一、动态规划
1. 框架
我自己的理解动态规划的方法本质是归纳、递推,是一种穷举的方法(只不过这种穷举比一般的暴力穷举减少许多不必要的操作)。所以动态规划有两个重点:
-
状态转移方程
状态转移方程即dp函数方程,这里又要明确几点:
(1)dp函数的自变量(即参数、或者说状态)是什么
(2)dp函数的值代表什么
(3)从一个状态到另一个状态有哪些选择
-
确定base case
在进行递推时,显然是需要一个初始的已知结果
(1)自顶向下
<1>暴力递归
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5GbVzsjw-1616289657177)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613983497588.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6QwR6YH8-1616289657180)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613983556730.png)]
<2>备忘录法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRA2f2ft-1616289657182)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613983651760.png)]
(2)自底向上
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpqVbV0W-1616289657185)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613984144281.png)]
2. 应用例题
(1)凑零钱问题
给你 k 种⾯值的硬币,⾯值分别为 c1, c2 … ck ,每种硬 币的数量⽆限,再给⼀个总⾦额 amount ,问你最少需要⼏枚硬币凑出这个 ⾦额,如果不可能凑出,算法返回 -1 。
-
确定递推关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HrGhVTCU-1616289657187)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613985266051.png)]
-
确定状态
也就是原问题和⼦问题中变化的变量。由于硬币数量⽆ 限,所以唯⼀的状态就是⽬标⾦额 amount 。
-
确定dp含义
当前的⽬标⾦额是 n ,⾄少需要 dp(n) 个硬 币凑出该⾦额。
-
确定择优选择
也就是对于每个状态,可以做出什么选择改变当 前状态。具体到这个问题,⽆论当的⽬标⾦额是多少,选择就是从⾯额列表 coins 中选择⼀个硬币,然后⽬标⾦额就会减少
-
明确basecase
显然⽬标⾦额为 0 时,所需硬币数量为 0;当⽬标⾦额 ⼩于 0 时,⽆解,返回 -1
1. 暴力递归
def coinChange(coins: List[int], amount: int):
def dp(n):
# base case
if n == 0: return 0
if n < 0: return -1
# 求最⼩值,所以初始化为正⽆穷
res = float('INF')
for coin in coins:
subproblem = dp(n - coin)
# ⼦问题⽆解,跳过
if subproblem == -1: continue
res = min(res, 1 + subproblem)
return res if res != float('INF') else -1 return dp(amount)
2. 带备忘录
def coinChange(coins: List[int], amount: int):
# 备忘录
memo = dict() def dp(n):
# 查备忘录,避免重复计算
if n in memo:
return memo[n]
if n == 0:
return 0
if n < 0:
return -1
res = float('INF')
for coin in coins:
subproblem = dp(n - coin)
if subproblem == -1: continue
res = min(res, 1 + subproblem)
# 记⼊备忘录
memo[n] = res if res != float('INF') else -1
return memo[n]
return dp(amount)
3. 自底向上
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwvXVzWX-1616289657189)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613985814946.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z8h2Tw09-1616289657190)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613985843679.png)]
(2)股票买卖问题
p[i]:第i天股票的价格
<1>买卖股票最佳时机1
只能交易一次(买入一次+卖出一次)
设:dp[ i ]为在第i天卖出股票所能获得的最大利润
则:dp[ i ] = max( dp[ i - 1] + p[ i ] - p[ i -1] , 0 )
<2>买卖股票最佳时机2
不限交易次数(但手里不能同时有多个股票)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XRGOssez-1616289657191)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615106377867.png)]
<3>买卖股票最佳时机3
最多两次交易
<4>买卖股票最佳时机4
最多K笔交易
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i647SJUW-1616289657192)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615108252133.png)]
<5>买卖股票最佳时机含冷冻期
<6>买卖股票最佳时机含手续费
(3)打家劫舍问题
1.相邻的屋子不能抢
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xV9ivkpB-1616289657194)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615109097207.png)]
2.首位也算作相邻
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JfDhSn0i-1616289657195)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615109207026.png)]
3.房子在二叉树的节点上,相连的两个房子不能同时被抢劫
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E9NhzSYD-1616289657195)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615109463291.png)]
(4)背包问题
1.01背包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QyBs75y1-1616289657196)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615110183865.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExokHXQM-1616289657197)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615109895741.png)]
2.完全背包(每个物品数量任意多)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-brxlst8F-1616289657198)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615110308680.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a9KOdZ3h-1616289657199)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615110405119.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZmFBXvQ-1616289657200)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615110508297.png)]
(5)实现计算器
(6)nSum问题
1.twoSum
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k3yR1YoQ-1616289657201)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615117514990.png)]
2.3sum
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odludH4M-1616289657202)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615118010903.png)]
(7)高楼扔鸡蛋
(8)衡量不同字符串之间的距离
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XTTbuY4m-1616289657203)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615127126178.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCgPaOZ1-1616289657203)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615127151130.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MYMQb87D-1616289657204)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615127521531.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHLCS2kU-1616289657205)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615130718140.png)]
(9)最长递增子序列
1.先定义dp[i]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g0CYkLBJ-1616289657206)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615180740470.png)]
注意,也就是这个递增序列的最后一个数字必须是nums[i],在这种情况下最长长度可以达到多大
2.basecase
dp[0] = 1
显然,只有一个数字的时候,那最大递增子序列就是其本身,长度为1
3.状态转移方程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJJyfB1M-1616289657207)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615181633578.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eZ68mhVa-1616289657208)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615181531086.png)]
注意,根据dp[i]的定义,最后返回的结果并不是dp[len(nums)-1],而应该是max(dp)
(10)最长公共子序列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXEdOuUq-1616289657209)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615168296107.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHdFGuPk-1616289657210)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615168639954.png)]
先定义basecase:
显然,若其中一个字符串的长度为0,则其公共子序列的长度也是0,则:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tPiuuQ1e-1616289657210)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615179429065.png)]
再定义状态转移方程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cmc3gGIP-1616289657211)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615179892700.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kg3YAx8T-1616289657212)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615180074010.png)]
改成自底向上的方式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imLfB1Wn-1616289657213)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615180279202.png)]
(11)最长回文子串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SnisYleL-1616289657214)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615182908339.png)]
(12)最大子数组和
注意:子序列是可以不连续的,但子数组是连续的
不方便用滑动窗口法,因为数组中含有数字,不好确定什么时候窗口的左右端滑动
与最长递增子序列类似,这道题的dp[i]定义需要注意:
不要定义成:dp[i]为nums[:i]的最大子数组和
要定义成:dp[i]为:若这个子数组以nums[i]结尾,则其最大和可以达到多少
状态转移方程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8jGuYfW-1616289657215)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615184782773.png)]
basecase:
显然dp[0] = nums[0]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XSfuxHIP-1616289657216)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615184899034.png)]
(13)接雨水问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzIMoFCK-1616289657217)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615185897562.png)]
二、回溯算法
回溯的本质也是穷举,遍历,而且复杂度很高,适当的剪枝操作是必要的
1. 框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a35sIH0R-1616289657218)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613986025100.png)]
2. 应用例题
(1)全排列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bmQ04Ehc-1616289657219)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613986565133.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cj25jSok-1616289657220)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613986587826.png)]
(3)N皇后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4TBXnE6g-1616289657222)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613986828328.png)]
(3)扔鸡蛋
若干层楼,若干个鸡蛋,让你算出最少的尝试次数,找到鸡蛋恰好摔不碎的那层楼
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KGQcnnvY-1616289657223)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613987232236.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fScqMO3T-1616289657223)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1613987281001.png)]
三、BFS算法
核心思想:
-
用于求解图中某两个结点的最短距离
-
如何将问题抽象成图的模型:
(1)状态
每个状态在图中是一个结点,不同状态之间可以相互转化(也即这两点之间有连线)
要注意这个状态转换是单向还是双向的(也即是有向图还是无向图)
(2)转化、联系、路径
这在图中对应结点之间有连线
-
注意点
(1)一定要用visited列表记录已经访问过得结点,否则一定超时!
(2)不同场景下每个结点可能有不同数目的相连结点,可能每个结点的邻接结点数目是相同的,也可能不同
(3)大While循环里,每次需要遍历当前temp集合里的所有结点,如果遇到目标则返回,否则将temp集合里 所有结点的所有邻接结点加入到一个temp1,然后temp = temp1,进行下次循环,直到temp1为空时 结束循环
// 计算从起点 start 到终点 target 的最近距离
int BFS(Node start, Node target) {
Queue<Node> q; // 核⼼数据结构
Set<Node> visited; // 避免⾛回头路
q.offer(start); // 将起点加⼊队列
visited.add(start);
int step = 0; // 记录扩散的步数
while (q not empty) {
int sz = q.size();
/* 将当前队列中的所有节点向四周扩散 */
for (int i = 0; i < sz; i++) {
Node cur = q.poll();
/* 划重点:这⾥判断是否到达终点 */
if (cur is target)
return step;
/* 将 cur 的相邻节点加⼊队列 */
for (Node x : cur.adj())
if (x not in visited) {
q.offer(x);
visited.add(x);
}
}
/* 划重点:更新步数在这⾥ */
step++;
}
}
四、DFS算法
五、滑动窗口算法
1. 框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VrbQEJTX-1616289657224)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615090366957.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-96RENYwp-1616289657225)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615091965734.png)]
2. 应用例题
(1)最小覆盖子串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgehcYUJ-1616289657226)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615091994971.png)]
(2)字符串排列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hVhHlT1-1616289657227)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615092391713.png)]
(3)找所有字母异位词
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ofG7Y4F0-1616289657229)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615092488786.png)]
(4)最长无重复子串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FwS87Bga-1616289657230)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1615092583968.png)]
DFS算法
五、滑动窗口算法
1. 框架
[外链图片转存中…(img-VrbQEJTX-1616289657224)]
[外链图片转存中…(img-96RENYwp-1616289657225)]
2. 应用例题
(1)最小覆盖子串
[外链图片转存中…(img-fgehcYUJ-1616289657226)]
(2)字符串排列
[外链图片转存中…(img-5hVhHlT1-1616289657227)]
(3)找所有字母异位词
[外链图片转存中…(img-ofG7Y4F0-1616289657229)]
(4)最长无重复子串
[外链图片转存中…(img-FwS87Bga-1616289657230)]