【玩转算法】动态规划

  1. 什么是动态规划?

    1. 它既是一种数学优化的方法,同时也是编程的方法。DP将原问题拆解成若干子问题,同时保存子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案。
    2. 动态规划是数学优化的方法
      1. 动态规划是数学优化的方法指,动态规划要解决的都是问题的最优解。而一个问题的最优解是由它的各个子问题的最优解决定的。
      2. 由此引出动态规划的第一个重要的属性:最优子结构。一般由最优子结构,推导出一个状态转移方程 f(n),就能很快写出问题的递归实现方法。通过求子问题的最优解,可以获得原问题的最优解。
    3. 动态规划是编程的方法
      1. 动态规划是编程的方法指,可以借助编程的技巧去保证每个重叠的子问题只会被求解一次。动态规划本质是递归问题,递归中发现了重叠子问题
      2. 引出了动态规划的第二个重要的属性:重叠子问题
      3. 记忆化搜索自顶向下的解决方法,指将已经计算出来的结果保存起来,那么下次遇到相同的输入时,直接返回保存好的结果,能够有效节省了大量的计算时间。由于递归的解法需要耗费非常多的重复计算,而且很多计算都是重叠的,记忆化搜索能避免重叠计算
      4. 记忆化搜索能将问题规模不断减少,但是由于有了递归的存在,程序运行时对堆栈的消耗以及处理是很慢的,在实际工作中并不推荐。更好的办法是自底向上
      5. 动态规划是自底向上的解决方法,指通过状态转移方程,从最小的问题规模入手,不断地增加问题规模,直到所要求的问题规模为止。同样使用记忆化避免重复的计算,不需要递归。
  2. 动态规划面试题分类

    1. 运用动态规划去解决问题,最难的地方有两个:应当采用什么样的数据结构来保存什么样的计算结果。如何利用保存下来的计算结果推导出状态转移方程。第一个难点,不仅是为了避免重复的计算,也是推导状态转移方程的关键。这一难点往往是在把问题规模缩小的过程中进行的。
    2. 解决技巧:假设已经把所有子问题的最佳结果都计算出来了,那么只需要考虑,如何根据这些子问题的结果来得出最终的答案。根据动态规划问题的难易程度,把常见的动态规划面试题分成如下三大类。
      1. 线性规划
        1. 面试题中最常见也是最简单的一种。线性,就是说各个子问题的规模以线性的方式分布,并且子问题的最佳状态或结果可以存储在一维线性的数据结构里,例如一维数组,哈希表等。解法中,经常会用 dp[i] 去表示第 i 个位置的结果,或者从 0 开始到第 i 个位置为止的最佳状态或结果。
        2. 求解 dp[i] 的复杂程度取决于题目的要求,但是基本上有两种形式。
          1. 求解 dp[i] 形式一。第一种形式,当前所求的值仅仅依赖于有限个先前计算好的值,也就是说,dp[i] 仅仅依赖于有限个 dp[j],其中 j < i。
          2. 求解 dp[i] 形式二。第二种求解 dp[i] 的形式,当前所求的值依赖于所有先前计算好的值,也就是说,dp[i] 是各个 dp[j] 的某种组合,其中 j 由 0 遍历到 i−1。
      2. 区间规划
        1. 区间规划,就是说各个子问题的规模由不同的区间来定义,一般子问题的最佳状态或结果存储在二维数组里。一般用 dp[i][j] 代表从第 i 个位置到第 j 个位置之间的最佳状态或结果。
        2. 解这类问题的时间复杂度一般为多项式时间,对于一个大小为 n 的问题,时间复杂度不会超过 n 的多项式倍数。例如,O(n)=n^k,k 是一个常数,根据题目的不同而定。
      3. 约束规划
        1. 在普通的线性规划和区间规划里,一般题目有两种需求:统计和最优解。
        2. 这些题目不会对输出结果中的元素有什么限制,只要满足最终的一个条件就好了。但是在很多情况下,题目会对输出结果的元素添加一定的限制或约束条件,增加了解题的难度。
  3. 动态规划问题初探

    1. LeetCode 第 70 题:爬楼梯
    2. LeetCode 第 120 题:三角形最小路径和
    3. LeetCode 第 64 题:最小路径和
    4. LeetCode 第 343 题:整数拆分
    5. LeetCode 第 279 题:完全平方数
  4. 发现重叠子问题

    1. LeetCode 第 343 题:整数拆分
    2. LeetCode 第 279 题:完全平方数
    3. LeetCode 第 91 题:解码方法
    4. LeetCode 第 62 题:不同路径
    5. LeetCode 第 63 题: 不同路径 II
  5. 状态的定义和状态转移

    1. LeetCode 第 198 题:打家劫舍
    2. LeetCode 第 213 题:打家劫舍 II
    3. LeetCode 第 337 题:打家劫舍 III
    4. LeetCode 第 309 题:最佳买卖股票时机含冷冻期
  6. 面试中的0-1背包问题

    1. LeetCode 第 416 题:分割等和子集
    2. LeetCode 第 322 题:零钱兑换
    3. LeetCode 第 377 题:组合总和 Ⅳ
    4. LeetCode 第 474 题:一和零,注意:什么叫组成?必须用完?还是有剩余就可以?
    5. LeetCode 第 139 题:单词拆分
    6. LeetCode 第 494 题:目标和
  7. 子序列问题

    1. LeetCode 第 300 题:最长上升子序列,关注:什么是子序列?什么是上升?一个序列可能有多个最长上升子序列;但这个最长的长度只有1个,如何返回?全部返回如何排序?

    2. LeetCode 第 376 题:摆动序列

    3. LeetCode 第 1143 题:最长公共子序列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值