从简单的动态规划问题探讨解决动态规划的核心

如果某一问题有很多重叠子问题,使用动态规划是最有效的。

动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。

什么是动态规划

动态规划,英文:Dynamic Programming,简称DP,是一种通过把复杂问题分解为相对简单的子问题,再从子问题的解得到原问题的解的方法。

动态规划的解题步骤

动态规划的解题步骤如下:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

动态规划应该如何debug

破除这个问题的最好方式就是把dp数组打印出来,看看究竟是不是按照自己思路推导的!

动态规划的应用场景

动态规划的应用场景主要有以下几种:

  1. 最短路径问题:比如求解一个图中从一个节点到另一个节点的最短路径,动态规划可以解决这个问题。
  2. 最大子数组问题:比如求解一个数组中连续子数组的最大和,动态规划可以解决这个问题。
  3. 背包问题:比如求解一个背包问题,动态规划可以解决这个问题。
  4. 股票问题:比如求解一个股票的最大利润,动态规划可以解决这个问题。
  5. 数学问题:比如求解一些数学问题,动态规划可以解决这个问题。

动态规划的核心思想

动态规划的核心思想是分治法,即将原问题分解为子问题,然后递归求解子问题,最后合并子问题的解得到原问题的解。

动态规划的核心是状态转移方程,即如何从子问题的解得到原问题的解。

找出最长的神奇数列【简单算法实例】


问题描述

小F是一个好学的中学生,今天他学习了数列的概念。他在纸上写下了一个由 0 和 1 组成的正整数序列,长度为 n。这个序列中的 1 和 0 交替出现,且至少由 3 个连续的 0 和 1 组成的部分数列称为「神奇数列」。例如,10101 是一个神奇数列,而 1011 不是。现在,小F想知道在这个序列中,最长的「神奇数列」是哪一个。你能帮他找到吗?

如果有多个神奇数列,那么输出最先出现的一个。


测试样例:
样例1:

输入:inp = “0101011101”
输出:’010101’

样例2:

输入:inp = “1110101010000”
输出:’10101010’

样例3:

输入:inp = “1010101010101010”
输出:’1010101010101010’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def solution(inp):
dp = [0] * len(inp)
dp[0] = 1
for i in range(1, len(inp)):
if inp[i-1] == inp[i]:
dp[i] = 1
else:
dp[i] = dp[i-1] +1

max_len = max(dp)

if max_len < 3:
return ""

start_index = dp.index(max_len) - max_len + 1
return inp[start_index:start_index + max_len]

if __name__ == "__main__":
print(solution("0101011101") == "010101")

题解思路:

  1. 确定dp数组(dp table)以及下标的含义:我们可以使用一个一维的dp数组来记录以当前字符结尾的最长神奇数列的长度。
    • dp[i] 表示以 inp[i] 结尾的最长神奇数列的长度。
  2. 确定递推公式:
    • 如果 inp[i-1] == inp[i],则 dp[i] = dp[i-1] + 1。
    • 如果 inp[i-1]!= inp[i],则 dp[i] = 1。
  3. dp数组如何初始化:
    • dp[0] = 1,因为以 0 结尾的最长神奇数列的长度肯定是 1。
  4. 确定遍历顺序:我们从第二个字符开始遍历到字符串的末尾,依次更新 dp 数组。
  5. 举例推导dp数组:
    • 假设当前字符为 0,则 dp[0] = 1。
    • 假设当前字符为 1,则 dp[1] = 1。
    • 假设当前字符为 0,则 dp[2] = 1。
    • 假设当前字符为 1,则 dp[3] = 2。
    • 假设当前字符为 0,则 dp[4] = 1。
    • 假设当前字符为 1,则 dp[5] = 2。
    • 假设当前字符为 0,则 dp[6] = 1。
    • 假设当前字符为 1,则 dp[7] = 2。
    • 假设当前字符为 0,则 dp[8] = 1。
    • 假设当前字符为 1,则 dp[9] = 2。
    • 假设当前字符为 0,则 dp[10] = 1。

总结

动态规划问题的解决方法大致分为以上五步,其余优化等等,仍需在实际问题中不断总结。