【算法扫盲】从暴力递归到动态规划

1、暴力递归

1)把问题转化为规模缩小了的同类问题的子问题
2)有明确的不需要继续进行递归的条件[base case]
3)有当得到了子问题的结果之后的决策过程
4)不记录每一个子问题的解

① 打印n层汉诺塔从最左边移动到最右边的全部过程

【算法扫盲】从暴力递归到动态规划_第1张图片

② 给定一个栈,不能申请额外的数据结构,使用递归方式来逆序这个栈

【算法扫盲】从暴力递归到动态规划_第2张图片

③ 打印一个字符串的全部子序列

【算法扫盲】从暴力递归到动态规划_第3张图片

④ 打印一个字符串的全部子序列,且不出现重复字面值的子序列

【算法扫盲】从暴力递归到动态规划_第4张图片

⑤ 打印一个字符串的全部排列,要求不出现重复的排列

【算法扫盲】从暴力递归到动态规划_第5张图片

⑥ 规定1和A对应,2和B对应,3和C对应...
那么一个数字字符串比如"111"就可以转化为"AAA"、"KA"、"AK"
给定一个只有数字字符组成的字符串str,返回有多少种转化结果

【算法扫盲】从暴力递归到动态规划_第6张图片【算法扫盲】从暴力递归到动态规划_第7张图片

⑦ 给定两个长度都为N的数组weights和values,
weights[i]和values[i]分别代表i号物品的重量和价值。
给定一个正数bag,表示一个载重bag的袋子,
袋子中可以装的物品不能超过这个重量,
返回袋子中能装下的最多的价格是多少?

【算法扫盲】从暴力递归到动态规划_第8张图片

⑧ 给定一个整型数组arr,代表数值不同的纸牌排成一条线,
玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,
但是每个玩家每次只能拿走最左或最右的纸牌,
双方玩家都不会在对方单独改变策略的情况下让对方得到收益,
请返回最后获胜者的分数。

【算法扫盲】从暴力递归到动态规划_第9张图片

⑨ N皇后问题
在N*N的棋盘上摆N个皇后,要求任何两个皇后不同行、不同列、不同斜线
给定一个正数N,返回N皇后的摆法有多少种:
N=1,返回1
N=2或3,2皇后和3皇后问题无论怎么摆都不行,返回0
N=8,返回92

【算法扫盲】从暴力递归到动态规划_第10张图片【算法扫盲】从暴力递归到动态规划_第11张图片

目前N皇后的问题已经是最优解,业内研究了这么些年,已经是最好的试法,在试法上已经没有突破了。所以N皇后问题现在也是各个国家大型机器验证计算能力的经典题目,所以在试法上已经到头了。但是在常数项方面可以继续优化加速,使用位运算来进行常数项的优化后,时间上可以获得指数级别的提升。

【算法扫盲】从暴力递归到动态规划_第12张图片

2、动态规划

什么暴力递归可以继续优化?

① 有重复同一个子问题的解,这种递归可以优化;

② 如果一个子问题都是不同的解,无法优化也不用优化。

假设有排成一行的N个位置,记为1~N,N一定大于或等于2
开始时机器人在其中的M位置上(M一定是1~N中的一个)
如果机器人来到1位置,那么下一步只能往右来到2位置
如果机器人来到N位置,那么下一步只能往右来到N-1位置
如果机器人来到中间位置,那么下一步可以往左或往右走
规定机器人必须走K步,最终能来到P位置(P也是1~N中的一个)的方法有多少种
给定4个参数:N、M、K、P,返回方法数

暴力递归:

【算法扫盲】从暴力递归到动态规划_第13张图片【算法扫盲】从暴力递归到动态规划_第14张图片

动态规划:

【算法扫盲】从暴力递归到动态规划_第15张图片

任何一个动态规划,都是由暴力尝试的种子改过来的。暴力递归其实是最最自然的智慧,最符合人类第一反应的思维。在暴力递归的循环中,一步一步去分析其中的必要性,从而转为动态规划。但并不是所有的暴力递归都可转为动态规划,有时候暴力递归的重复性没有那么深,也完全没有必要改为动态规划。说到底,动态规划就是把参数组合完成结构化的缓存。常见的4种尝试改为动态规划的暴力递归模型:

1)从左往右的尝试模型

2)范围上的尝试模型

3)多样本位置对应的尝试模型

4)寻找业务限制的尝试模型

下面看几例上面的用暴力递归解决的问题,尝试优化成动态规划:

第⑥题,由暴力递归改为动态规划

【算法扫盲】从暴力递归到动态规划_第16张图片

第⑦题,由暴力递归改为动态规划

【算法扫盲】从暴力递归到动态规划_第17张图片

第⑧题,由暴力递归改为动态规划

【算法扫盲】从暴力递归到动态规划_第18张图片

给定一个字符串str和一个字符串类型的数组arr
arr里面的每一个字符串代表一张贴纸,可以把单个字符剪开使用,目的是拼出str
返回需要多少张贴纸可以完成这个任务?

比如:str="babac",arr={"ba", "c", "abcd"}
答案:至少需要两张贴纸"ba"和"abcd"。因为使用这两张贴纸,把每一个字符单独剪开
含有2个a,2个b,1个c,是可以拼出str的,故返回2

【算法扫盲】从暴力递归到动态规划_第19张图片【算法扫盲】从暴力递归到动态规划_第20张图片

其实从上面的例子中可以看出,在解决一个问题的时候可能有很多可尝试的方法。在众多的尝试方法中,又会产生很多动态规划的方式,也就是说,一个问题可能会有若干种动态规划的解法。那么如何找到某个问题的动态规划方式?

1)分析一个暴力递归是否存在重复调用;

2)找到哪些参数的变化会影响返回值,对每一个列出变化范围;

3)参数间所有的组合数量,意味着表大小;

4)记忆化搜索的方法就是傻缓存,非常容易得出;

5)规定好严格表的大小,分析位置的依赖顺序,然后从基础填写到最终解;

6)对于有枚举行为的决策过程,进一步优化。

两个字符串的最长公共子序列问题

【算法扫盲】从暴力递归到动态规划_第21张图片

给定一个数组,代表每个人喝完咖啡准备刷杯子的时间
只有一台咖啡机,一次只能洗一只杯子,时间耗费a,洗完才能洗下一杯
每个咖啡杯也可以自己挥发干净,时间耗费b,咖啡杯可以并行挥发
返回让所有咖啡杯变干净的最早完成时间

暴力递归

【算法扫盲】从暴力递归到动态规划_第22张图片

动态规划

【算法扫盲】从暴力递归到动态规划_第23张图片

你可能感兴趣的:(算法扫盲,算法)