【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];
    }
}
相关推荐
Jinkxs6 分钟前
Java 跨域14-Java 与区块链(Hyperledger)集成
java·开发语言·区块链
8Qi816 分钟前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
绿算技术41 分钟前
万卡推理集群存储选型分析:从核心架构到应用视角
大数据·科技·算法·架构
晨曦中的暮雨1 小时前
Golang速通(Javaer版)
java·开发语言·后端·golang
七老板的blog1 小时前
当 Spring StateMachine 遇见大模型:构建工业级 AI 写作流水线
java·人工智能·spring
想吃火锅10052 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
云烟成雨TD2 小时前
Spring AI 1.x 系列【46】MCP Security 模块
java·人工智能·spring
CRMEB系统商城2 小时前
CRMEB多商户系统(Java)v2.3公测版发布
java·开发语言·人工智能·小程序·开源·php
sinat_255487812 小时前
第七部分。介绍MVC(模型-视图-控制器)模式
java·ide·http·tomcat·intellij-idea