从简单的动态规划问题探讨解决动态规划的核心 | 豆包MarsCode AI刷题

115 阅读4分钟

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

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

如果你的学习过程遇到了些许困难,不妨试试MarscodeAI,这是进步的一种方式。

什么是动态规划

动态规划,英文: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'

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。

总结

动态规划问题的解决方法大致分为以上五步,其余优化等等,仍需在实际问题中不断总结,在此过程中Marscode也给我提供了很大帮助,毋庸置疑,AI在逐步迈入人类的方方面面。