[Algorithm][动态规划][动态规划原理][整体理解]详细讲解


0.前言

  • 本节非常重要哦,有关后面动态规划题的总体理解
  • 建议和后面的题搭配起来食用哦~

1.动态规划一般思路

  • 创建dp
    • 可能是一维数组,也可能是二维数组
  • 确定状态表示 -> dp[i]的含义
  • 推导状态转移方程 -> dp[i] = ?
    • 用之前或之后的值,推导出dp[i]的值
    • 根据最近的一步,来划分问题
  • 初始化:保证填表的时候不越界
  • 确定填表顺序:为了保证填写当前状态的时候,所需要的状态已经计算过了
  • 确定返回值
    • 题目要求 + 状态标识

2.状态表示如何来?

  • 题目要求
  • 经验 + 题目要求
    • 一维线性dp
      • i位置为结尾
      • i位置为起点
  • 分析问题的过程中,发现重复子问题

3.状态转移方程如何推导?

  • 简单问题可以直接写出状态转移方程
  • 复杂问题,多个状态时,可以画图表示各个状态的关系,最后对着关系机写出状态转移方程
    请添加图片描述

4.处理边界问题以及初始化问题的技巧

  • 虚拟结点如何开?

    • 一维dp表多开一位

      • 注意事项
        • 虚拟节点里面的值,要保证后面填表时是正确的
        • 下标的映射关系
          请添加图片描述
    • 二维dp表多开一行和一列

      • 注意事项
        • 虚拟节点里面的值,要保证后面填表时是正确的
        • 下标的映射关系
          请添加图片描述
  • 算法里面初始化为无穷:INT_MAX || INT_MIN时,要注意潜在的溢出风险

    • 替换为0x3f3f3f3f || -0x3f3f3f3f即可解决该问题
    • 首先它足够大,其次它没有溢出风险
  • 多个状态方程,其中只有一部分的状态方程需要特殊的初始化,那么可以想办法把这个状态方程拆成多步,分步执行,尝试避免特殊处理初始化

  • 根据实际情况,可以考虑将dp表中的值,都初始化为最次的情况

    • 这样处理或许可以省去一些步骤
  • 关于字符串dp问题,空串是有研究意义的

    • 引入空串后,会方便初始化
    • 倘若在dp表中加入了虚拟结点,那么可以在初始化时,在源字符串前面加上' '
      • 这是为了确保字符串下标正确,避免在字符串中找子串时不必要的麻烦

5.空间优化思路

  • 优化方法
    • 滚动数组
  • 优化效果
    • O ( N 2 ) − > O ( N ) O(N^2) -> O(N) O(N2)>O(N)
    • O ( N ) − > O ( 1 ) O(N) -> O(1) O(N)>O(1)

6.子序列 vs 子数组

  • 子序列
    • 相对顺序是跟源字符串/数组是一致的
    • 但是元素和元素之间,在源字符串/数组中可以是不连续的
    • 一般时间复杂度: O ( 2 n ) O(2^n) O(2n)
  • 子数组
    • 在源字符串/数组中挑出来,必须是连续的
    • 一般时间复杂度: O ( N 2 ) O(N^2) O(N2)
  • 子序列其实相当于包含了子数组