适用场景
- 问题可以拆成若干
子问题 - 当前状态的答案可以由
更小规模的状态推出来 - 子问题会被
重复计算 - 题目要求
最值、方案数、是否可行,通常都可能是动态规划
核心思路
- 先定义
dp[i]或dp[i][j]的含义 - 找出状态之间的
转移方程 - 明确
初始状态 - 按照正确顺序填表或记忆化搜索,最终得到答案
Rust 模板
1 | fn dp_template(nums: Vec<i32>) -> i32 { |
爬楼梯
1 | fn climb_stairs(n: i32) -> i32 { |
代表题
5. 最长回文子串
题意:给定一个字符串,找出其中最长的回文子串。
1 | pub fn longest_palindrome(s: String) -> String { |
32. 最长有效括号
题意:给定一个只包含左右括号的字符串,求最长合法括号子串的长度。
1 | pub fn longest_valid_parentheses(s: String) -> i32 { |
62. 不同路径
题意:机器人从左上角走到右下角,每次只能向右或向下,求不同路径总数。
1 | pub fn unique_paths(m: i32, n: i32) -> i32 { |
64. 最小路径和
题意:给定一个非负整数网格,从左上角走到右下角,每次只能向右或向下,求路径数字总和的最小值。
1 | pub fn min_path_sum(grid: Vec<Vec<i32>>) -> i32 { |
70. 爬楼梯
题意:每次可以爬1或2阶楼梯,给定楼梯总阶数n,求有多少种不同爬法。
1 | pub fn climb_stairs(n: i32) -> i32 { |
72. 编辑距离
题意:给定两个单词,求将一个单词转换成另一个单词所需的最少操作数,操作包括插入、删除、替换。
1 | pub fn min_distance(word1: String, word2: String) -> i32 { |
118. 杨辉三角
题意:给定一个非负整数numRows,生成杨辉三角的前numRows行。
1 | pub fn generate(num_rows: i32) -> Vec<Vec<i32>> { |
139. 单词拆分
题意:给定一个字符串和一个字典,判断该字符串能否被拆分成若干个字典中的单词。
1 | use std::collections::HashSet; |
152. 乘积最大子数组
题意:给定一个整数数组,求乘积最大的连续子数组。
1 | pub fn max_product(nums: Vec<i32>) -> i32 { |
198. 打家劫舍
题意:给定一个数组表示每间房屋的钱数,不能偷相邻的房屋,求能偷到的最大金额。
1 | pub fn rob(nums: Vec<i32>) -> i32 { |
279. 完全平方数
题意:给定一个整数n,求和为n的完全平方数的最少数量。
1 | pub fn num_squares(n: i32) -> i32 { |
300. 最长递增子序列
题意:给定一个整数数组,找出其中严格递增子序列的最大长度,子序列不要求连续。
1 | pub fn length_of_lis(nums: Vec<i32>) -> i32 { |
322. 零钱兑换
题意:给定若干种硬币面额和目标金额amount,求凑出该金额所需的最少硬币数;如果无法凑出则返回-1。
1 | pub fn coin_change(coins: Vec<i32>, amount: i32) -> i32 { |
1143. 最长公共子序列
题意:给定两个字符串,求它们的最长公共子序列长度,子序列中的字符顺序不能改变,但不要求连续。
1 | pub fn longest_common_subsequence(text1: String, text2: String) -> i32 { |