4.22 编辑距离-1

This commit is contained in:
zhangsan 2025-04-22 16:03:25 +08:00
parent 263bc7481f
commit ba2c826ff3
3 changed files with 134 additions and 0 deletions

View File

@ -0,0 +1,57 @@
package dynamic_programming;
/**
* 题目 392. 判断子序列 (isSubsequence)
* 描述给定字符串 s t 判断 s 是否为 t 的子序列
* 字符串的一个子序列是原始字符串删除一些也可以不删除字符而不改变剩余字符相对位置形成的新字符串例如"ace""abcde"的一个子序列"aec"不是
*
* 进阶
* 如果有大量输入的 S称作 S1, S2, ... , Sk 其中 k >= 10亿你需要依次检查它们是否为 T 的子序列在这种情况下你会怎样改变代码
示例 1
输入s = "abc", t = "ahbgdc"
输出true
* 链接https://leetcode.cn/problems/is-subsequence/
*/
//不会
public class IsSubsequence {
//动态规划转为求最长公共子序列是否为s的长度
public boolean isSubsequence(String s, String t) {
int length1 = s.length(); int length2 = t.length();
int[][] dp = new int[length1+1][length2+1];
for(int i = 1; i <= length1; i++){
for(int j = 1; j <= length2; j++){
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = dp[i][j-1]; //s长度肯定小于等于t 要删也删t
}
}
}
return dp[length1][length2] == length1;
}
//双指针
/**
* 我们用两个指针 i 遍历字符串 sj 遍历字符串 t初始均指向各自字符串的开头
*
* 如果 s.charAt(i) == t.charAt(j)说明匹配上了两个指针都往后走i++, j++
* 否则就只能在 t 跳过这个字符j++
* i 走到 s.length() 说明 s 中的所有字符都在 t 中按顺序找到了返回 true否则 j 扫完 t 还没把 s 的所有字符匹配完就返回 false
*/
public boolean isSubsequence2(String s, String t) {
int i = 0, j = 0;
int n = s.length(), m = t.length();
// i < n j < m 时循环
while (i < n && j < m) {
if (s.charAt(i) == t.charAt(j)) {
// 匹配时两指针都前进一步
i++;
}
// 不匹配时只在 t 上跳过
j++;
}
// 如果 i 已经走完 s说明全部匹配
return i == n;
}
}

View File

@ -0,0 +1,33 @@
package dynamic_programming;
/**
* 题目 64. 最小路径和 (MinPathSum)
* 描述给定一个包含非负整数的 m x n 网格 grid 请找出一条从左上角到右下角的路径使得路径上的数字总和为最小
* 说明每次只能向下或者向右移动一步
示例 1
输入grid = [[1,3,1],[1,5,1],[4,2,1]]
输出7
解释因为路径 13111 的总和最小
* 链接https://leetcode.cn/problems/minimum-path-sum/
*/
public class MinPathSum {
public int minPathSum(int[][] grid) {
int r=grid.length;
int c=grid[0].length;
int[][]dp=new int[r][c];
dp[0][0]=grid[0][0];
for (int i = 1; i < r; i++) {
dp[i][0]=dp[i-1][0]+grid[i][0];
}
for (int i = 1; i < c; i++) {
dp[0][i]=dp[0][i-1]+grid[0][i];
}
for (int i = 1; i < r; i++) {
for (int j = 1; j < c; j++) {
dp[i][j]=Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return dp[r-1][c-1];
}
}

View File

@ -0,0 +1,44 @@
package dynamic_programming;
/**
* 题目 115. 不同的子序列 (numDistinct)
* 描述给你两个字符串 s t 统计并返回在 s 子序列 t 出现的个数
*
* 测试用例保证结果在 32 位有符号整数范围内
示例 1
输入s = "rabbbit", t = "rabbit"
输出3
解释
如下所示, 3 种可以从 s 中得到 "rabbit" 的方案
rabbbit
rabbbit
rabbbit
* 链接https://leetcode.cn/problems/distinct-subsequences/
*/
//不会
public class NumDistinct {
public int numDistinct(String s, String t) {
int n = s.length(), m = t.length();
// dp[i][j]: s[0..i-1] t[0..j-1] 的方案数
long[][] dp = new long[n+1][m+1];
// 初始化
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}
// dp[0][j>0] 默认就是 0
// 状态转移
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s.charAt(i-1) == t.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
} else {
dp[i][j] = dp[i-1][j];
}
}
}
// 由于题目保证答案在 32 位范围内最后转为 int 返回
return (int) dp[n][m];
}
}