Bootstrap

Java 动态规划 二维数组 详解

在 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];
}

总结

二维数组在动态规划中的应用广泛且多样,关键在于理解如何将问题分解成子问题,并使用表格来存储这些子问题的解。通过适当地初始化和更新这些数组,可以有效地解决各种动态规划问题。

;