在 Java 中使用动态规划(Dynamic Programming, DP)解决问题时,经常会用到二维数组来存储中间结果。二维数组作为动态规划表(DP table)是理解和实现动态规划算法的关键部分。下面我将详细解释二维动态规划数组的概念、初始化和实际应用。
1. 概念
动态规划是一种算法策略,用于解决具有重叠子问题和最优子结构的问题。在很多情况下,为了保存子问题的解,我们需要使用二维数组(或称为矩阵)来存储这些解,其中每个元素代表一个子问题的解。
2. 初始化二维数组
在 Java 中初始化二维数组通常如下:
int[][] dp = new int[n][m]; // 其中 n 和 m 分别是数组的行和列的大小
这个数组 dp
可以根据问题的需求来初始化一些基础值。例如,在很多问题中,可能需要将边界设置为特定值以处理边界条件。
3. 实际应用
以下是几种常见的使用二维动态规划数组的问题类型和示例:
3.1. 最小路径和
这是一个经典问题,通常在一个给定的二维网格中找到从左上角到右下角的最小路径和。
问题描述:
给定一个包含非负整数的 m x n
网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
示例代码:
public int minPathSum(int[][] grid) {
int m = grid.length, 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];
}
// 填充剩余的 dp 表
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[m - 1][n - 1];
}
3.2. 编辑距离(Levenshtein distance)
问题描述:
给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数。
示例代码:
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
// 初始化 dp 表
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= n; j++) {
dp[0][j] = j;
}
// 计算所有 dp 值
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] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
}
}
return dp[m][n];
}
总结
二维数组在动态规划中的应用广泛且多样,关键在于理解如何将问题分解成子问题,并使用表格来存储这些子问题的解。通过适当地初始化和更新这些数组,可以有效地解决各种动态规划问题。