leecode更新
This commit is contained in:
parent
108863a5a8
commit
1f674b6b56
|
|
@ -1,5 +1,7 @@
|
||||||
package com.markilue.leecode.dynamic.second;
|
package com.markilue.leecode.dynamic.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*@BelongsProject: Leecode
|
*@BelongsProject: Leecode
|
||||||
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||||
|
|
@ -15,7 +17,78 @@ package com.markilue.leecode.dynamic.second;
|
||||||
*/
|
*/
|
||||||
public class T34_NumDistinct {
|
public class T34_NumDistinct {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
String s = "rabbbit", t = "rabbit";
|
||||||
|
// String s = "babgbag", t = "bag";
|
||||||
|
System.out.println(numDistinct1(s,t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:本质上实际上是从是不是子序列变为了 有多少个子序列的问题
|
||||||
|
* TODO 不同的子序列:
|
||||||
|
* 1.dp定义: dp[i][j]表示使用s[0-i]能凑出多少个t[0-j]
|
||||||
|
* 2.dp状态转移方程:
|
||||||
|
* dp[i][j]的状态分为两种 :
|
||||||
|
* if s[i]==t[j] 原本能继续凑出 dp[i][j]=dp[i-1][j-1]+dp[i-1][j]
|
||||||
|
* else 不能继续凑出 dp[i][j]=dp[i-1][j]
|
||||||
|
* 3.dp初始化:
|
||||||
|
* 4.dp遍历顺序:
|
||||||
|
* 5.dp举例推导:以s = "rabbbit", t = "rabbit"为例
|
||||||
|
* [0 r a b b i t]
|
||||||
|
* 0: 1 0 0 0 0 0 0
|
||||||
|
* r: 1 1 0 0 0 0 0
|
||||||
|
* a: 1 1 1 0 0 0 0
|
||||||
|
* b: 1 1 1 1 0 0 0
|
||||||
|
* b: 1 1 1 2 1 0 0
|
||||||
|
* b: 1 1 1 3 3 0 0
|
||||||
|
* i: 1 1 1 3 3 3 0
|
||||||
|
* t: 1 1 1 3 3 3 3
|
||||||
|
* 速度击败26.62% 内存击败32.5% 16ms
|
||||||
|
* @param s
|
||||||
|
* @param t
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int numDistinct(String s, String t) {
|
public int numDistinct(String s, String t) {
|
||||||
|
|
||||||
|
int[][] dp = new int[s.length() + 1][t.length() + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
dp[i][0] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < dp.length; i++) {
|
||||||
|
for (int j = 1; j < dp[0].length; j++) {
|
||||||
|
//证明之前匹配上过,那么在之前匹配上的基础上+后来匹配上的次数:一部分是用s[i - 1]来匹配;一部分是不用s[i - 1]来匹配
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[s.length()][t.length()];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一维dp优化
|
||||||
|
* 速度击败73.25% 内存击败99.63% 11ms
|
||||||
|
* @param s
|
||||||
|
* @param t
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int numDistinct1(String s, String t) {
|
||||||
|
|
||||||
|
int[] dp = new int[t.length() + 1];
|
||||||
|
|
||||||
|
dp[0] = 1;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 1; i < s.length()+1; i++) {
|
||||||
|
for (int j = t.length(); j >0; j--) {//因为要使用之前的j-1所以就反向遍历
|
||||||
|
if (s.charAt(i - 1) == t.charAt(j - 1)) dp[j] += dp[j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[t.length()];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.markilue.leecode.dynamic.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-24 10:32
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣583题 两个字符串的删除操作:
|
||||||
|
* 给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。
|
||||||
|
* 每步 可以删除任意一个字符串中的一个字符。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T35_MinDistance {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
String word1 = "leetcode", word2 = "etco";
|
||||||
|
System.out.println(minDistance(word1,word2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路: 每个字符串都能删
|
||||||
|
* TODO DP五部曲:
|
||||||
|
* 1.dp定义:dp[i][j]表示使用word1[i]变为word2[j]需要删除的数量
|
||||||
|
* 2.dp状态转移方程:
|
||||||
|
* 1.当word1[i]==word2[j]时 则不需要多加操作
|
||||||
|
* dp[i][j]=dp[i-1][j-1]
|
||||||
|
* 2.当word1[i]!=word2[j]时 则需要在之前多加操作
|
||||||
|
* dp[i][j]= min(dp[i-1][j]+1,dp[i][j-1]+1)
|
||||||
|
* 3.dp初始化: dp[i][0]=i dp[0][j]=j
|
||||||
|
* 4.dp遍历顺序:
|
||||||
|
* 5.dp举例推导:以word1 = "leetcode", word2 = "etco"为例
|
||||||
|
* [0 e t c o]
|
||||||
|
* 0 0 1 2 3 4
|
||||||
|
* l 1 2 3 4 5
|
||||||
|
* e 2 1 2 3 4
|
||||||
|
* e 3
|
||||||
|
* t 4
|
||||||
|
* c 5
|
||||||
|
* o 6
|
||||||
|
* d 7
|
||||||
|
* e 8
|
||||||
|
* 速度击败62.53% 内存击败39.37% 7ms
|
||||||
|
* @param word1
|
||||||
|
* @param word2
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int minDistance(String word1, String word2) {
|
||||||
|
|
||||||
|
int[][] dp = new int[word1.length() + 1][word2.length() + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
dp[i][0] = i;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < dp[0].length; i++) {
|
||||||
|
dp[0][i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < dp.length; i++) {
|
||||||
|
for (int j = 1; j < dp[0].length; j++) {
|
||||||
|
if (word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];
|
||||||
|
else dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[word1.length()][word2.length()];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.markilue.leecode.dynamic.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-24 11:09
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣72题 编辑距离:
|
||||||
|
* 给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。
|
||||||
|
* 你可以对一个单词进行如下三种操作:
|
||||||
|
* 插入一个字符
|
||||||
|
* 删除一个字符
|
||||||
|
* 替换一个字符
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T36_MinDistance {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
String word1 = "horse", word2 = "ros";
|
||||||
|
System.out.println(minDistance(word1,word2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:更复杂的地方在于 编辑存在三种操作: 应该如何处理
|
||||||
|
* TODO dp五部曲:
|
||||||
|
* 1.dp定义:dp[i][j]表示word1[0-i]通过三种操作最少能花多少步变成word2[0-j]
|
||||||
|
* 2.dp状态转移方程:
|
||||||
|
* 1.当word1[i]!=word1[j]时 删除 修改 插入
|
||||||
|
* dp[i][j]=min(dp[i-1][j]+1,dp[i-1][j-1]+1,dp[i][j-1]+1)
|
||||||
|
* else dp[i][j]=dp[i-1][j-1]
|
||||||
|
* 3.dp初始化:
|
||||||
|
* 4.dp遍历顺序:
|
||||||
|
* 5.dp举例推导:
|
||||||
|
* 速度击败45.95% 内存击败14.7% 5ms
|
||||||
|
* @param word1
|
||||||
|
* @param word2
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int minDistance(String word1, String word2) {
|
||||||
|
|
||||||
|
int[][] dp = new int[word1.length() + 1][word2.length() + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
dp[i][0]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < dp[0].length; i++) {
|
||||||
|
dp[0][i]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < dp.length; i++) {
|
||||||
|
for (int j = 1; j < dp[0].length; j++) {
|
||||||
|
if(word1.charAt(i-1)==word2.charAt(j-1)) dp[i][j]=dp[i-1][j-1];
|
||||||
|
else dp[i][j]=Math.min(Math.min(dp[i-1][j]+1,dp[i-1][j-1]+1),dp[i][j-1]+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[word1.length()][word2.length()];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toCharArray()优化
|
||||||
|
* 速度击败95.84% 内存击败60.85%
|
||||||
|
* @param word1
|
||||||
|
* @param word2
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int minDistance1(String word1, String word2) {
|
||||||
|
|
||||||
|
int[][] dp = new int[word1.length() + 1][word2.length() + 1];
|
||||||
|
char[] char1 = word1.toCharArray();
|
||||||
|
char[] char2 = word2.toCharArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
dp[i][0]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < dp[0].length; i++) {
|
||||||
|
dp[0][i]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < dp.length; i++) {
|
||||||
|
for (int j = 1; j < dp[0].length; j++) {
|
||||||
|
if(char1[i-1]==char2[j-1]) dp[i][j]=dp[i-1][j-1];
|
||||||
|
else dp[i][j]=Math.min(Math.min(dp[i-1][j]+1,dp[i-1][j-1]+1),dp[i][j-1]+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[word1.length()][word2.length()];
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue