跳至主要內容

面试中设计暴力递归过程的原则

mozzie大约 4 分钟算法算法

面试中设计暴力递归过程的原则

暴力递归和动态规划的关系

  • 某一个暴力递归,有解的重复调用,就可以把这个暴力递归优化成动态规划
  • 任何动态规划问题,都一定对应着某一个有重复过程的暴力递归,但不是所有的暴力递归,都一定对应着动态规划

原则

  1. 每一个可变参数的类型,一定不要比int类型更加复杂
  2. 原则1)可以违反,让类型突破到一维线性结构,那必须是单一可变参
  3. 如果发现原则1)被违反,但不违反原则2),只需要做到记忆化搜索即可
  4. 可变参数的个数,能少则少
  5. 递归函数的可变参数不能是数组类型,一个可变参数就是一维表,两个可变参数就是二维表。

如何找到某个问题的动态规划方式?

  1. 设计暴力递归:重要原则+4种常见尝试模型!重点!
    • 从左往右的尝试模型
    • 范围上的尝试模型
    • 多样本位置全对应的尝试模型
    • 寻找业务限制的尝试模型
  2. 分析有没有重复解:套路解决
  3. 用记忆化搜索->用严格表结构实现动态规划:套路解决
  4. 看看能否继续优化:套路解决

暴力递归到动态规划的套路

  1. 你已经有了一个不违反原则的暴力递归,而且的确存在解的重复调用
  2. 找到哪些参数的变化会影响返回值,对每一个列出变化范围
  3. 参数间的所有的组合数量,意味着表大小
  4. 记忆化搜索的方法就是傻缓存,非常容易得到
  5. 规定好严格表的大小,分析位置的依赖顺序,然后从基础填写到最终解
  6. 对于有枚举行为的决策过程,进一步优化

记住求解的方式有两种

  1. 自顶向下的备忘录法
  2. 自底向上。

在求解问题中,对于每一步决策,列出各种可能的局部解,再依据某种判定条件,舍弃那些肯定不能得到最优解的局部解,在每一步都经过筛选,以每一步都是最优解来保证全局是最优解。

如何分析有没有重复解

  1. 列出调用过程,可以只列出前几层
  2. 有没有重复解,一看便知

动态规划的进一步优化

  1. 空间压缩
  2. 状态化简
  3. 四边形不等式
  4. 其他优化技巧

滚动数组是DP中的一种编程思想。简单的理解就是让数组滚动起来,每次都使用固定的几个存储空间,来达到压缩,节省存储空间的作用。起到优化空间,主要应用在递推或动态规划中。因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N很大的情况下可以达到压缩存储的作用。

知道了面试中设计暴力递归过程的原则,然后呢?一定要逼自己找到不违反原则情况下的暴力尝试!如果你找到的暴力尝试,不符合原则,马上舍弃!找新的!如果某个题目突破了设计原则,一定极难极难,面试中出现概率低于5%!

暴力转成动态规划总结:

  1. 暴力递归的return值,dp也要进行赋值。
  2. 暴力的递归尝试改成从dp中取值。
  3. 递归参数是减,那么dp的for循环就是从小到大,从初始数据先写0也能看出来是从小到大循环
  4. 递归返回的参数是min。那么在递归中最上面min = Integer.MaxValue, 就需要给dp数组都赋值为此。而不是继续使用min
  5. 写递归方法时,判定停止条件可以是index == nums.length 也可以是index == nums.length - 1,这个停止条件适合那种小人移动问题,比如说一个m*n 数组最短路径,爬楼梯,打家劫舍;其余的都用index == nums.length

将一个问题拆成几个子问题,分别求解这些子问题,即可推断出大问题的解

贡献者: mozzie