《LeetCode砍怪升级系列》动态规划篇


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


题目列表

【第1题】最长有效括号 ⭐️⭐️⭐️

LeetCode地址:https://leetcode.cn/problems/longest-valid-parentheses/

1.题目描述

在这里插入图片描述

2.解题思路

我们从左到右依次遍历字符串,依次计算出cur指针所指的字符的往左的最长扩充有效区域。
在这里插入图片描述
如图中(1)所示,当cur指向"(“时并以该括号结尾时,其往左的最长扩充有效区域为0。
如图中(2)所示,当cur指向”)"时,我们需要知道以cur左边括号结尾的字符的有效区域长度,以计算出pre的位置。之后再判断cur和pre指向的括号是否匹配。如果不匹配,则cur位置的最长扩充有效区域为0,如图中3。否则,cur位置的最长扩充有效区域为(cur前一个位置的最长扩充有效区域长度+2)+(pre前一个位置的最长扩充有效区域长度)。

3.代码详解

class Solution {
    public int longestValidParentheses(String s) {
        if(s == null || s.length() < 2){
            return 0;
        }

        //dp[i]:子串必须以i位置结尾的情况下,往左最远能扩充出多长有效区域

        int[] dp = new int[s.length()];
        dp[0] = 0;//以0位置结尾,没有有效括号区域
        for(int i = 1; i < s.length(); i++){
            if(s.charAt(i) == '('){//以该位置结尾的字符串不可能有有效区域
                dp[i] = 0;
            }else{ // 以 ')' 结尾
                //通过dp[i-1]找出(...)左括号的位置 pre,即 '('...),其中...的长度为dp[i-1]的长度
                int pre = i - dp[i-1] - 1;
                if(pre >= 0){
                    if(s.charAt(pre) == '('){
                        dp[i] = dp[i-1] + 2 ;
                        if(pre - 1 >= 0){
                            dp[i] += dp[pre - 1];
                        }
                    }else{
                      dp[i] = 0;
                    }
                }
            }
        }
        int max = 0;
        for(int x : dp){
            max = Math.max(max,x);
        }
        return max;
    }
}

【第2题】编辑距离 ⭐️⭐️⭐️

LeetCode地址:https://leetcode.cn/problems/edit-distance/

1.题目描述

在这里插入图片描述

2.解题思路

动态规划:dp[i][j]表示word1[1…i]和word2[1…j]的编辑距离大小
数组初始化如下和中间格子填充情况如下:
在这里插入图片描述
在计算dp[i][j]时,一共有四种情况(1)插入一个字符,向长对齐(2)删除一个字符,向短对齐(3)长度相同,最后一个字符不相同,替换一个字符(4)长度相同,最后一个字符相同,不需要操作

3.代码详解

class Solution {
    public int minDistance(String word1, String word2) {
        int N = word1.length();
        int M  = word2.length();
        int[][] dp = new int[N+1][M+1]; //从word1[0,..,i]到word2[0,...,j]的编辑距离
        dp[0][0] = 0;

        for(int i = 1; i < N + 1;i++){
            dp[i][0] = i;
        }
        for(int j = 1; j < M + 1; j++){
            dp[0][j] = j;
        }
        for(int i =1; i < N + 1; i++){
            for(int j = 1; j < M + 1; j++){
                // aab acb 等于=> aa ac 的编辑距离
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    // abc aad
                    //否则替换一次:在 ab aa 的编辑距离基础上 + 1
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                // 从 aab aa 增加一个字符得到 aab
                dp[i][j] = Math.min(dp[i][j],dp[i][j-1] +1);
                // 从 aab aa 删除一个字符得到 aa
                dp[i][j] = Math.min(dp[i][j],dp[i-1][j] +1);
                //上面三者取最小
            }
        }
        return dp[N][M];
    }
}

【第3题】最小路径和 ⭐️

LeetCode地址:https://leetcode.cn/problems/minimum-path-sum/

1.题目描述

在这里插入图片描述

2.解题思路

简单的样本对应模型

3.代码详解

class Solution {
    public int minPathSum(int[][] grid) {
        int N = grid.length;
        int M = grid[0].length;
        int[][] dp = new int[N][M];

        dp[0][0] = grid[0][0];

        for(int i = 1; i < M;i++){
            dp[0][i] = grid[0][i] + dp[0][i-1];
        }

        for(int i = 1; i < N;i++){
            dp[i][0] = grid[i][0] + dp[i-1][0];
        }

        for(int i = 1; i < N; i++){
            for(int j = 1; j < M; j++){
                int p1 = grid[i][j] + dp[i][j-1];
                int p2 = grid[i][j] + dp[i-1][j];
                dp[i][j] = Math.min(p1,p2);
            }
        }

        return dp[N-1][M-1];

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值