力扣动态规划练习题(编辑距离、最大矩形)

188 阅读1分钟

编辑距离

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ed…

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符

示例 1:

输入:word1 = "horse", word2 = "ros"

输出:3

解释:

horse -> rorse (将 'h' 替换为 'r')

rorse -> rose (删除 'r')

rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"

输出:5

解释:

intention -> inention (删除 't')

inention -> enention (将 'i' 替换为 'e')

enention -> exention (将 'n' 替换为 'x')

exention -> exection (将 'n' 替换为 'c')

exection -> execution (插入 'u')

提示:

  • 0 <= word1.length, word2.length <= 500
  • word1 和 word2 由小写英文字母组成

代码

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] = Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
                }
            }
        }
        
        return dp[m][n];
    }
}

思路分析

  1. 创建一个二维数组dp,其中dp[i][j]表示将word1的前i个字符转换成word2的前j个字符所需的最少操作数。

  2. 初始化边界条件,即当一个单词为空时,需要的操作数等于另一个单词的长度。即dp[i][0] = idp[0][j] = j

  3. 使用动态规划的方法求解最小操作数。

  4. 对于dp[i][j],有以下情况:

    • 如果word1的第i个字符等于word2的第j个字符,则不需要进行操作,即dp[i][j] = dp[i-1][j-1]

    • 如果word1的第i个字符不等于word2的第j个字符,则需要进行操作。操作有三种情况:

      • 插入操作:在word1的第i个字符后插入word2的第j个字符,即dp[i][j] = dp[i][j-1] + 1
      • 删除操作:删除word1的第i个字符,即dp[i][j] = dp[i-1][j] + 1
      • 替换操作:将word1的第i个字符替换为word2的第j个字符,即dp[i][j] = dp[i-1][j-1] + 1
    • 取这三种操作的最小值作为dp[i][j]的值。

最大矩形

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ma…

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]

输出:6

解释:最大矩形如上图所示。

示例 2:

输入:matrix = []

输出:0

示例 3:

输入:matrix = [["0"]]

输出:0

示例 4:

输入:matrix = [["1"]]

输出:1

示例 5:

输入:matrix = [["0","0"]]

输出:0

提示:

  • rows == matrix.length
  • cols == matrix[0].length
  • 1 <= row, cols <= 200
  • matrix[i][j] 为 '0' 或 '1'

代码

class Solution {
    public int maximalRectangle(char[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return 0;
        }
        
        int m = matrix.length;
        int n = matrix[0].length;
        
        int[] heights = new int[n];
        int maxArea = 0;
        
        for (int i = 0; i < m; i++) {
            // 更新每一列的高度
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == '1') {
                    heights[j] += 1;
                } else {
                    heights[j] = 0;
                }
            }
            
            // 计算当前行的最大矩形面积
            maxArea = Math.max(maxArea, largestRectangleArea(heights));
        }
        
        return maxArea;
    }
    
    private int largestRectangleArea(int[] heights) {
        Stack<Integer> stack = new Stack<>();
        int maxArea = 0;
        int n = heights.length;
        
        for (int i = 0; i <= n; i++) {
            int h = (i == n) ? 0 : heights[i];
            
            if (stack.isEmpty() || h >= heights[stack.peek()]) {
                stack.push(i);
            } else {
                int top = stack.pop();
                int width = stack.isEmpty() ? i : i - 1 - stack.peek();
                maxArea = Math.max(maxArea, heights[top] * width);
                i--;
            }
        }
        
        return maxArea;
    }
}

思路分析

  1. 定义一个一维数组 heights,其长度为矩阵的列数。该数组用于存储当前行到上一行连续 '1' 的高度。

  2. 初始化一个变量 maxArea 用于记录最大矩形的面积。

  3. 遍历矩阵的每一行:

    • 更新每一列的高度:若当前位置为 '1',则将该列的高度加 1;否则,将该列的高度重置为 0。
    • 计算当前行的最大矩形面积:调用 largestRectangleArea 方法,传入 heights 数组,计算最大矩形面积,并与 maxArea 进行比较,更新最大面积值。
  4. 实现 largestRectangleArea 方法:

    • 使用单调栈来解决柱状图中最大矩形的问题。
    • 遍历数组 heights,将每个元素的索引入栈,如果遇到比栈顶元素小的元素,则出栈并计算以出栈元素为高度的矩形面积,更新最大面积值。