【LeetCode 手撕算法】(多维动态规划)不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离

二维的dp

62-不同路径

**思路:**记录每一位置的路线数,初始值最上最左设为1,dp i j =dp i-1 j +dp i j-1

**注意:**注意边界从1开始遍历

java 复制代码
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 i=0;i<n;i++){
            dp[0][i]=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];
    }
}

64-最小路径和

**思路:**设置第一个位置初始值,由此设置上和右边界的初始值(累加)。开始遍历x位置 先判断上和左位置谁最小,然后加上当前位置,即所求值。返回最后一个。

注意: 边界已初始化,则遍历时从1开始

java 复制代码
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 i=1;i<n;i++){
            dp[0][i]=dp[0][i-1]+grid[0][i];
        }
        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];
    }
}

5-最长回文子串

**思路:**用dp i j 来表示长度为i到j的是否回文,先判断特殊情况s为空,再判断长度为1,为2时;再执行长度为3,用start取匹配时的位置,用maxlen更新匹配时的最大长度。

核心判断:s.charAt( i )==s.charAt( j )&&dp i+1 j-1

**注意:**判断完边界再判断内部是否回文;

获取元素用charAt( ) , 截取用substring( i, j )

循环用长度len来走外循环

java 复制代码
class Solution {
    public String longestPalindrome(String s) {
        int n=s.length();
        if(n<2) {return s;}//s长度为0,1时
        boolean [][]dp =new boolean[n][n];//代表判断长度i,j之间的内容
        int maxlen=1; //用于结果返回,最大长度
        int start =0;//用于结果返回,开始值
        for(int i=0;i<n;i++){//初始化长度为1的
            dp[i][i]=true;
        }
        for(int i=0;i<n-1;i++){//初始化长度为2的
            if(s.charAt(i)==s.charAt(i+1)){
                dp[i][i+1]=true; //初始化i和i+1区间的值(长度为2)
                if(maxlen<2){  //更新取值
                    maxlen=2;
                    start=i;  //获取当前i(从0开始遍历的)
                }
            }
        }
        //从头开始,走s长度为3及以上的情况
        for(int len=3;len<=n;len++){
            for(int i=0;i+len<=n;i++){
                int j=i+len-1;  //右边界的值
                //判断边界是否回文,以及内部是否回文,小的值已初始
                if(s.charAt(i)==s.charAt(j)&&dp[i+1][j-1]){ 
                    dp[i][j]=true;
                    if(maxlen<len){
                        maxlen=len; //更新最长值
                        start=i;    //获取当前i(从0开始遍历的)
                    }
                }
            }
        }
        return s.substring(start,start+maxlen);//截取用substring()函数
    }
}

1143-最长公共子序列

思路:dp i j 表示text1 i text2 j 的最长相同序列数,判断两串对应位置是否相同,并加一,否则选dp i-1 j 或者**dp i j -1**的最大值

注意: 求数字则初始值为索引,从0开始,长度为n+1;

遍历时从1索引开始,可等于m、n , 判断方式看 n-1 是否越界

java 复制代码
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];//存两个位置i和j相同字符的最大数量
        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][j-1],dp[i-1][j]);
                }
            }
        }
        return dp[m][n];
    }
}

72-编辑距离

思路:

情况 1:

dp[0][j] = j:空字符串变成 word2[0..j-1],需要插入 j 个字符

dp[i][0] = iword1[0..i-1] 变成空字符串,需要删除 i 个字符

情况 2:word1[i-1] == word2[j-1] 不用做任何操作,直接继承之前的结果:

dpij = dpi-1j-1

情况 3:word1[i-1] != word2[j-1] 三种操作取最小值:

java 复制代码
dp[i][j] = min(
    dp[i-1][j] + 1,    // 删除 word1[i-1]
    dp[i][j-1] + 1,    // 插入 word2[j-1]
    dp[i-1][j-1] + 1   // 替换
)

**注意:**求数字则初始设置m+1长度,;

若相等则+1, 不等则考虑(删除、插入、替换)三者最小值,再+1;

注意条件边界取值

java 复制代码
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++){//若一串为0时
            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{
                    //不等时,选三个的最小值 并+1
                    dp[i][j]=Math.min(Math.min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1])+1;
                }
            }
        }
        return dp[m][n];
    }
}
相关推荐
MacroZheng22 分钟前
同事问我:"Claude Code经常失忆,不怕它把项目搞炸?",我:"怕,三个Markdown文件给它装个永不丢失的外置大脑!"
java·人工智能·后端
学习星球1 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
十年Java程序媛2 小时前
深度实战:JDK21 虚拟线程 + HikariCP 生产正确配比、坑点、监控全套
java·spring boot
xiaoqiMikko2 小时前
有人在搜一个不存在的 Tomcat 版本
java·tomcat
用户3126874877205 小时前
ConcurrentHashMap 怎么保证线程安全?从分段锁到 CAS+synchronized
java
vipxieliang5 小时前
ValidX vs Apache Commons Validator:功能与性能对比
java·spring boot
SimonKing5 小时前
升级Spring Boot 4后,从 Jackson 2 到 3,到底有哪些变化
java·后端·程序员
吃饱了得干活6 小时前
一篇讲清楚Spring Boot:自动装配、启动器、过滤器、拦截器、设计模式
java·spring boot·后端
alphaTao7 小时前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
lhldsg7 小时前
AI零售系统实战指南:从架构设计到落地部署全解析
java·人工智能·小程序·uni-app·零售