系列文章目录
力扣热题 100:哈希专题三道题详细解析(JAVA)
力扣热题 100:双指针专题四道题详细解析(JAVA)
力扣热题 100:滑动窗口专题两道题详细解析(JAVA)
力扣热题 100:子串专题三道题详细解析(JAVA)
力扣热题 100:普通数组专题五道题详细解析(JAVA)
力扣热题 100:矩阵专题四道题详细解析(JAVA)
力扣热题 100:链表专题经典题解析(前7道)
力扣热题 100:链表专题经典题解析(后7道)
力扣热题 100:二叉树专题经典题解析(前8道)
力扣热题 100:二叉树专题进阶题解析(后7道)
力扣热题 100:图论专题经典题解析
力扣热题 100:回溯专题经典题解析
力扣热题 100:二分查找专题经典题解析
力扣热题 100:栈专题经典题解析
力扣热题 100:堆专题经典题解析
力扣热题 100:贪心算法专题经典题解析
力扣热题 100:动态规划专题经典题解析
力扣热题 100:多维动态规划专题经典题解析
力扣热题 100:技巧专题经典题解析
文章目录
- 系列文章目录
- 一、不同路径(题目 62)
- 1. 题目描述
- 2. 示例
- 3. 解题思路
- 4. 代码实现(Java)
- 5. 复杂度分析
- 二、最小路径和(题目 64)
- 1. 题目描述
- 2. 示例
- 3. 解题思路
- 4. 代码实现(Java)
- 5. 复杂度分析
- 三、最长回文子串(题目 5)
- 1. 题目描述
- 2. 示例
- 3. 解题思路
- 4. 代码实现(Java)
- 5. 复杂度分析
- 四、最长公共子序列(题目 1143)
- 1. 题目描述
- 2. 示例
- 3. 解题思路
- 4. 代码实现(Java)
- 5. 复杂度分析
- 五、编辑距离(题目 72)
- 1. 题目描述
- 2. 示例
- 3. 解题思路
- 4. 代码实现(Java)
- 5. 复杂度分析
在力扣(LeetCode)平台上,多维动态规划相关的题目是算法面试和练习中的重要部分。今天,我们就来详细解析多维动态规划专题中的几道经典题目,帮助大家更好地理解解题思路和技巧。
一、不同路径(题目 62)
1. 题目描述
一个机器人位于一个 m x n 网格的左上角,只能向下或向右移动,求到达右下角的不同路径数。
2. 示例
示例 1:
输入:m = 3, n = 2
输出:3
3. 解题思路
这道题主要考察二维动态规划的应用。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示到达位置 (i, j)
的不同路径数。状态转移方程为 dp[i][j] = dp[i-1][j] + dp[i][j-1]
。
4. 代码实现(Java)
public class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
for (int j = 0; j < n; j++) {
dp[0][j] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}
5. 复杂度分析
- 时间复杂度 :O(m * n),需要遍历整个网格。
- 空间复杂度 :O(m * n),需要使用二维数组存储路径数。可以优化为 O(n) 空间,使用一维数组滚动更新。
二、最小路径和(题目 64)
1. 题目描述
给定一个 m x n 的网格 grid
,其中每个单元格包含一个非负整数,求从左上角到右下角的最小路径和。
2. 示例
示例 1:
输入:grid = [[1, 3, 1], [1, 5, 1], [4, 2, 1]]
输出:7
3. 解题思路
这道题主要考察二维动态规划的应用。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示到达位置 (i, j)
的最小路径和。状态转移方程为 dp[i][j] = grid[i][j] + Math.min(dp[i-1][j], dp[i][j-1])
。
4. 代码实现(Java)
public class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for (int i = 1; i < m; i++) {
dp[i][0] = dp[i-1][0] + grid[i][0];
}
for (int j = 1; j < n; j++) {
dp[0][j] = dp[0][j-1] + grid[0][j];
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = grid[i][j] + Math.min(dp[i-1][j], dp[i][j-1]);
}
}
return dp[m-1][n-1];
}
}
5. 复杂度分析
- 时间复杂度 :O(m * n),需要遍历整个网格。
- 空间复杂度 :O(m * n),需要使用二维数组存储路径和。可以优化为 O(n) 空间,使用一维数组滚动更新。
三、最长回文子串(题目 5)
1. 题目描述
给定一个字符串 s
,找到其中最长的回文子串。
2. 示例
示例 1:
输入:s = "babad"
输出:"bab"
3. 解题思路
这道题主要考察二维动态规划的应用。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示子串 s[i..j]
是否为回文子串。状态转移方程为 dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1]
。
4. 代码实现(Java)
public class Solution {
public String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
String result = "";
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
if (s.charAt(i) == s.charAt(j)) {
if (j - i <= 1) {
dp[i][j] = true;
} else {
dp[i][j] = dp[i+1][j-1];
}
if (dp[i][j] && j - i + 1 > result.length()) {
result = s.substring(i, j + 1);
}
}
}
}
return result;
}
}
5. 复杂度分析
- 时间复杂度 :O(n^2),需要遍历所有可能的子串。
- 空间复杂度 :O(n^2),需要使用二维数组存储回文状态。
四、最长公共子序列(题目 1143)
1. 题目描述
给定两个字符串 text1
和 text2
,求它们的最长公共子序列的长度。
2. 示例
示例 1:
输入:text1 = "abcde", text2 = "ace"
输出:3
3. 解题思路
这道题主要考察二维动态规划的应用。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示 text1
的前 i
个字符和 text2
的前 j
个字符的最长公共子序列长度。状态转移方程为:
- 如果
text1[i-1] == text2[j-1]
,则dp[i][j] = dp[i-1][j-1] + 1
。 - 否则,
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1])
。
4. 代码实现(Java)
public class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
int[][] dp = new int[m+1][n+1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[m][n];
}
}
5. 复杂度分析
- 时间复杂度 :O(m * n),需要遍历两个字符串的所有字符组合。
- 空间复杂度 :O(m * n),需要使用二维数组存储最长公共子序列长度。可以优化为 O(min(m, n)) 空间,使用一维数组滚动更新。
五、编辑距离(题目 72)
1. 题目描述
给定两个字符串 word1
和 word2
,求将 word1
转换为 word2
所需的最少操作数。允许的操作包括插入、删除和替换。
2. 示例
示例 1:
输入:word1 = "horse", word2 = "ros"
输出:3
3. 解题思路
这道题主要考察二维动态规划的应用。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示将 word1
的前 i
个字符转换为 word2
的前 j
个字符所需的最少操作数。状态转移方程为:
- 如果
word1[i-1] == word2[j-1]
,则dp[i][j] = dp[i-1][j-1]
。 - 否则,
dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
。
4. 代码实现(Java)
public class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m+1][n+1];
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (word1.charAt(i-1) == word2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = 1 + Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]);
}
}
}
return dp[m][n];
}
}
5. 复杂度分析
- 时间复杂度 :O(m * n),需要遍历两个字符串的所有字符组合。
- 空间复杂度 :O(m * n),需要使用二维数组存储操作数。可以优化为 O(min(m, n)) 空间,使用一维数组滚动更新。
以上就是力扣热题 100 中与多维动态规划相关的经典题目的详细解析,希望对大家有所帮助。在实际刷题过程中,建议大家多动手实践,理解解题思路的本质,这样才能更好地应对各种算法问题。