返回

LeetCode 376、329 和 301 的动态规划之旅:掌握 DP,轻松玩转 LeetCode

闲谈

动态规划简介

动态规划是一种经典的优化算法,通过将大问题分解成一系列较小的子问题,并逐一解决这些子问题,最终得到大问题的最优解。动态规划的关键在于,子问题的最优解可以由其子子问题的最优解推导出,因此我们可以通过递推的方式逐步求解所有子问题,最终得到大问题的最优解。

LeetCode 376:摆动序列

在 LeetCode 376 中,我们的目标是找到数组中最长的摆动序列,即数字序列中相邻的数字交替上升和下降。我们可以定义状态 dp[i] 表示以第 i 个数字结尾的最长摆动序列的长度。则有如下状态转移方程:

dp[i] = max(dp[j] + 1) for all j < i and nums[j] < nums[i]

其中,nums[i] 表示数组中的第 i 个数字。我们可以使用动态规划的思想,从第一个数字开始,依次计算每个数字作为结尾的最长摆动序列的长度,最终得到答案。

LeetCode 329:矩阵中的最长递增路径

在 LeetCode 329 中,我们面临的挑战是找出矩阵中从左上角到右下角的最长递增路径。我们可以定义状态 dp[i][j] 表示从位置 (i, j) 出发的最长递增路径的长度。则有如下状态转移方程:

dp[i][j] = max(dp[i - 1][j], dp[i][j - 1], dp[i + 1][j], dp[i][j + 1]) + 1

其中,dp[i][j] 的值必须满足以下条件之一:

  • dp[i][j] > dp[i - 1][j],即当我们从 (i - 1, j) 到 (i, j) 时,数字递增。
  • dp[i][j] > dp[i][j - 1],即当我们从 (i, j - 1) 到 (i, j) 时,数字递增。
  • dp[i][j] > dp[i + 1][j],即当我们从 (i + 1, j) 到 (i, j) 时,数字递增。
  • dp[i][j] > dp[i][j + 1],即当我们从 (i, j + 1) 到 (i, j) 时,数字递增。

LeetCode 301:删除无效的括号

在 LeetCode 301 中,我们的任务是删除最小数量的括号,使得括号序列有效。我们可以定义状态 dp[i][j] 表示字符串 s 从第 i 个字符到第 j 个字符的子串是否有效。则有如下状态转移方程:

dp[i][j] = True if s[i] == '(' and s[j] == ')' and dp[i + 1][j - 1] == True

其中,s[i] 和 s[j] 分别表示字符串 s 的第 i 个和第 j 个字符。我们可以使用动态规划的思想,从第一个字符开始,依次计算字符串中所有子串的有效性,最终得到答案。

结语

动态规划作为计算机科学中的一颗璀璨明珠,在 LeetCode 中有着广泛的应用。通过 LeetCode 376、329 和 301 这三道经典题目,我们深入探索了动态规划的解题思路、算法效率优化以及复杂度分析。希望这篇文章能够帮助您更深入地理解动态规划,并在未来的 LeetCode 征程中一往无前。