leecode更新
This commit is contained in:
parent
6e66e33c27
commit
6d39eb279d
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.markilue.leecode.dynamic.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-26 10:08
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣647题 回文子串:
|
||||||
|
* 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
|
||||||
|
* 回文字符串 是正着读和倒过来读一样的字符串。
|
||||||
|
* 子字符串 是字符串中的由连续字符组成的一个序列。
|
||||||
|
* 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T37_CountSubstrings {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
// String s="aaa";
|
||||||
|
String s="abc";
|
||||||
|
System.out.println(countSubstrings(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:和编辑距离系列有异曲同工之妙,也可以通过前面的是不是来判断后面的是不是 如aa是;baab是
|
||||||
|
* TODO DP五部曲:
|
||||||
|
* 1.dp定义:dp[i][j]表示以j开头,以i结尾的word是不是回文字符串
|
||||||
|
* 2.dp状态转移方程:
|
||||||
|
* if s[i]==s[j]
|
||||||
|
* dp[i][j]=dp[i-1][j+1]
|
||||||
|
* else
|
||||||
|
* 3.dp初始化: dp[i][i]=true
|
||||||
|
* 4.dp遍历顺序:
|
||||||
|
* 5.dp举例推导: 以s = "aaa"为例
|
||||||
|
* [a a a]
|
||||||
|
* a t t t
|
||||||
|
* a t t t
|
||||||
|
* a t t t
|
||||||
|
* 速度击败55.35% 内存击败43.32% 7ms
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int countSubstrings(String s) {
|
||||||
|
int length = s.length();
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
|
||||||
|
boolean[][] dp = new boolean[length][length];
|
||||||
|
int result = length;//i=j
|
||||||
|
|
||||||
|
//将初始化蕴藏在实际for里面
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
for (int j = 0; j < length; j++) {
|
||||||
|
if (i <= j) {
|
||||||
|
dp[i][j] = true;
|
||||||
|
} else if (chars[i] == chars[j]) {
|
||||||
|
dp[i][j] = dp[i - 1][j + 1];
|
||||||
|
if (dp[i][j]) result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码随想录解法:只有当char[i]==char[j]的时候才进行判断
|
||||||
|
* 速度击败62.97% 内存击败25.91% 4ms
|
||||||
|
* 快在只需要判断下三角
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int countSubstrings1(String s) {
|
||||||
|
boolean[][] dp = new boolean[s.length()][s.length()];
|
||||||
|
int result = 0;
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
|
||||||
|
// for (int i = 1; i < dp.length; i++) {
|
||||||
|
// for (int j = i ; j >= 0; j--) {
|
||||||
|
// if(chars[i]==chars[j]){
|
||||||
|
// if(i-j<=1){//情况一a 情况二aa
|
||||||
|
// result++;
|
||||||
|
// dp[i][j]=true;
|
||||||
|
// }else if(dp[i-1][j+1]){//情况三bab
|
||||||
|
// result++;
|
||||||
|
// dp[i][j]=true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
for (int j = i ; j >= 0; j--) {
|
||||||
|
if(chars[i]==chars[j]&&((i-j<=1)||dp[i-1][j+1])){
|
||||||
|
//三种情况简化后的版本
|
||||||
|
result++;
|
||||||
|
dp[i][j]=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 双指针法:可以以一个单词为中心;也可以以两个单词为中心
|
||||||
|
* 速度击败99.97% 内存击败61.2% 1ms
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int countSubstrings2(String s) {
|
||||||
|
int result = 0;
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
for (int i = 0; i < s.length(); i++) {//因为for是一直向前的,所以一定不会有重复
|
||||||
|
result += extend(chars, i, i, s.length()); // 以i为中心
|
||||||
|
result += extend(chars, i, i + 1, s.length()); // 以i和i+1为中心
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public int extend(char[] s, int i, int j, int n) {
|
||||||
|
int res = 0;
|
||||||
|
while (i >= 0 && j < n && s[i] == s[j]) {
|
||||||
|
i--;
|
||||||
|
j++;
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
package com.markilue.leecode.dynamic.second;
|
||||||
|
|
||||||
|
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-26 10:58
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣516题 最长回文子序列:
|
||||||
|
* 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
|
||||||
|
* 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T38_LongestPalindromeSubseq {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
// String s = "bbbab";
|
||||||
|
String s = "cbbd";
|
||||||
|
System.out.println(longestPalindromeSubseq(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:还是分为当前两个字符是不是相等的两种情况;由于是子序列,所以存在继承关系
|
||||||
|
* TODO DP五部曲:
|
||||||
|
* 1.dp定义: dp[i][j]表示以j开头,以i结尾的子序列的最长回文子序列
|
||||||
|
* 2.dp状态转移方程:
|
||||||
|
* 1.s[i]==s[j]
|
||||||
|
* dp[i][j]=dp[i-1][j+1]+2
|
||||||
|
* 2.s[i]!=s[j] 删一个看那个更大
|
||||||
|
* dp[i][j]=max(dp[i-1][j],dp[i][j+1])
|
||||||
|
* 3.dp初始化: dp[i][i]=1
|
||||||
|
* 4.dp遍历顺序:
|
||||||
|
* 5.dp举例推导:
|
||||||
|
* 两个if速度变慢 速度击败81.32% 内存击败49.22% 27ms
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int longestPalindromeSubseq(String s) {
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
int[][] dp = new int[chars.length][chars.length];
|
||||||
|
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
for (int j = i; j >= 0; j--) {//由于需要j+1
|
||||||
|
if (chars[i] == chars[j]) {
|
||||||
|
if (j == i) dp[i][j] = 1;//包含初始化
|
||||||
|
else dp[i][j] = dp[i - 1][j + 1] + 2;
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[chars.length - 1][0];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优化:一个if,初始化放外面
|
||||||
|
* 速度击败99.36% 内存击败15.5% 13ms
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int longestPalindromeSubseq1(String s) {
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
int[][] dp = new int[s.length()][s.length()];
|
||||||
|
for (int i = 0; i < dp.length; i++) {
|
||||||
|
dp[i][i]=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < dp.length; i++) {
|
||||||
|
for (int j = i-1; j >=0 ; j--) {
|
||||||
|
if(chars[i]==chars[j]){
|
||||||
|
dp[i][j]=dp[i-1][j+1]+2;
|
||||||
|
}else {
|
||||||
|
dp[i][j]=Math.max(dp[i-1][j],dp[i][j+1]);//掐头大还是去尾大
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[s.length()-1][0];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ public class T06_StrStr {
|
||||||
if (needle.charAt(index + 1) == haystack.charAt(i)) {
|
if (needle.charAt(index + 1) == haystack.charAt(i)) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if (index == needle.length() - 1) {
|
if (index == needle.length() - 1) {//全部都匹配上了,直接返回指定位置
|
||||||
return (i - needle.length() + 1);
|
return (i - needle.length() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +125,11 @@ public class T06_StrStr {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testk(){
|
||||||
|
String s="aabaaf";
|
||||||
|
System.out.println(getNext1(s));
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 官方获取next数组的方法:精髓在于这次的next[i]可以通过上一次的next[i-1]来获取,分为两种情况:
|
* 官方获取next数组的方法:精髓在于这次的next[i]可以通过上一次的next[i-1]来获取,分为两种情况:
|
||||||
* 1)如果next[i-1]的下一个数和next[i]的下一个数相等,那么最大子串一定是在上一个的基础上+1,对应下面的if的内容
|
* 1)如果next[i-1]的下一个数和next[i]的下一个数相等,那么最大子串一定是在上一个的基础上+1,对应下面的if的内容
|
||||||
|
|
@ -140,10 +145,10 @@ public class T06_StrStr {
|
||||||
for (int i = 1; i < needle.length(); ++i) {
|
for (int i = 1; i < needle.length(); ++i) {
|
||||||
//神奇的是,k既是长度又是上一次不相等的索引
|
//神奇的是,k既是长度又是上一次不相等的索引
|
||||||
while (k != -1 && needle.charAt(k + 1) != needle.charAt(i)) {
|
while (k != -1 && needle.charAt(k + 1) != needle.charAt(i)) {
|
||||||
k = next[k];
|
k = next[k];//不相等就取k+1的上一个词即k的next进行回退
|
||||||
}
|
}
|
||||||
if (needle.charAt(k + 1) == needle.charAt(i)) {
|
if (needle.charAt(k + 1) == needle.charAt(i)) {
|
||||||
++k;
|
++k;//找到相等的了,k++
|
||||||
}
|
}
|
||||||
next[i] = k;
|
next[i] = k;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue