【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];
    }
}
相关推荐
架构源启13 小时前
文档接入与智能解析:基于 Spring AI 1.1.x 的多格式解析、版面理解与结构化抽取
java·人工智能·spring
可编程芯片开发15 小时前
基于MATLAB的PEF湍流风场生成器模拟与仿真
算法
罗西的思考16 小时前
【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (9)--- Reward Judging
人工智能·算法·机器学习
2401_8414956416 小时前
【数据结构】B+树
数据结构·数据库·c++·b+树·概念·结构·操作原理
Mr.HeBoYan17 小时前
一次持续三天才出现的丢包故障——深入解析 DPDK Memory Ordering、rte_ring 与 CPU Memory Barrier (下)
linux·网络·算法·架构·dpdk
大模型码小白17 小时前
JAVA 集合框架进阶:List 与 Set 的深度解析与实战
java·开发语言·人工智能·windows·语言模型·list·ai编程
wabs66618 小时前
关于图论【深度优先搜索的理论基础】
算法·深度优先·图论
名字还没想好☜18 小时前
Go 的 time.Ticker 陷阱:定时任务里被忽略的内存泄漏与正确关闭
java·数据库·golang·go·定时器
皓月斯语18 小时前
【C++基础】三目运算符
开发语言·数据结构·c++
先吃饱再说18 小时前
LeetCode 101. 对称二叉树
算法