|
|
|
@ -0,0 +1,41 @@
|
|
|
|
|
## <center>动态规划</center>
|
|
|
|
|
|
|
|
|
|
  暴力递归就是尝试,暴力递归是动态规划的基础,暴力递归加上合理的剪枝和缓存就是动态规划。
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
### 暴力递归的步骤
|
|
|
|
|
|
|
|
|
|
* 把问题转化为规模缩小了的同类问题的子问题
|
|
|
|
|
* 有明确的不需要继续进行递归的条件(base case,递归终止条件)
|
|
|
|
|
* 有当得到了子问题的结果之后的决策过程
|
|
|
|
|
* 不记录每一个子问题的解
|
|
|
|
|
|
|
|
|
|
### 暴力递归的几个常见问题
|
|
|
|
|
|
|
|
|
|
#### 1、汉诺塔问题
|
|
|
|
|
|
|
|
|
|
  打印n层汉诺,塔从最左边移动到最右边的全部过程,每次只能移动一个圆盘,不能出现大盘叠在小盘上面的情况。可以分为3个步骤。
|
|
|
|
|
|
|
|
|
|
* 将1-> n-1 移动到中间
|
|
|
|
|
* 将n移动到右边
|
|
|
|
|
* 将1-> n-1移动到右边
|
|
|
|
|
|
|
|
|
|
#### 2、打印一个字符串的全部子序列
|
|
|
|
|
|
|
|
|
|
  依次考察每一个字符是否被选中,递归逻辑可以画成整颗二叉树。每次递归前移除当前字符,递归完以后恢复当前字符。
|
|
|
|
|
|
|
|
|
|
#### 3、打印一个字符串的全部子序列,要求不要出现重复字面值的子序列
|
|
|
|
|
|
|
|
|
|
  同上,加上set去重
|
|
|
|
|
|
|
|
|
|
#### 4、打印一个字符串的全部排列
|
|
|
|
|
|
|
|
|
|
  使用index和index后面的字符交换位置,index递增达到递归目的,index=str.length为递归终止条件。
|
|
|
|
|
|
|
|
|
|
#### 5、打印一个字符串的全部排列,要求不要出现重复的排列
|
|
|
|
|
|
|
|
|
|
  加上visited数组去重,避免重复的字符进行交换。
|
|
|
|
|
|
|
|
|
|
#### 6、反转栈,不能使用额外集合,只能使用递归函数
|
|
|
|
|
|
|
|
|
|
  两个递归函数,reverse使用f函数拿到栈底元素,然后递归,将栈底元素压栈。利用局部变量保存栈底元素,系统函数调用栈保证所有元素逆序。f函数拿到栈底元素,并保证其他元素顺序不变。
|