leecode更新

This commit is contained in:
dingjiawen 2022-09-12 14:37:24 +08:00
parent 48fa58f8f2
commit bb316cd55c
2 changed files with 230 additions and 0 deletions

View File

@ -0,0 +1,63 @@
package com.markilue.leecode.string;
import org.junit.Test;
import java.util.Arrays;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.string
* @Author: dingjiawen
* @CreateTime: 2022-09-12 12:15
* @Description: TODO 力扣459题:重复的子字符串:
* 给定一个非空的字符串 s 检查是否可以通过由它的一个子串重复多次构成
* @Version: 1.0
*/
public class RepeatedSubstringPattern {
@Test
public void test() {
String s = "abcabcabc";
System.out.println(repeatedSubstringPattern(s));
// int[] next1 = getNext1(s);
// System.out.println(Arrays.toString(next1));
}
/**
* 这一题也可以用经典的KMP算法进行解决,又KMP算法可知:如果string由重复子字符串组成其next数组一定是前面全是-1,后面全是升序排列
* "abcabcabc",其next数组为[-1, -1, -1, 0, 1, 2, 3, 4, 5],所以规律是最后一个数+1可以整除是-1的数
* 速度击败74.63%内存击败10.85%
* @param s
* @return
*/
public boolean repeatedSubstringPattern(String s) {
int[] next1 = getNext1(s);
int length = next1.length;
if (next1[length - 1] != -1 && length % (length - next1[length - 1] - 1) == 0) {
return true;
}
return false;
}
public int[] getNext1(String needle) {
int[] next = new int[needle.length()];
next[0] = -1;
int k = -1;
for (int i = 1; i < needle.length(); ++i) {
while (k != -1 && needle.charAt(k + 1) != needle.charAt(i)) {
k = next[k];
}
if (needle.charAt(k + 1) == needle.charAt(i)) {
++k;
}
next[i] = k;
}
return next;
}
}

View File

@ -0,0 +1,167 @@
package com.markilue.leecode.string;
import org.junit.Test;
import java.util.Arrays;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.string
* @Author: dingjiawen
* @CreateTime: 2022-09-12 09:01
* @Description: TODO 力扣28题:实现strStr()
* 实现strStr()函数
* 给你两个字符串haystack needle 请你在 haystack 字符串中找出 needle 字符串出现的第一个位置下标从 0 开始如果不存在则返回 -1
* <p>
* 说明
* 当needle是空字符串时我们应当返回什么值呢这是一个在面试中很好的问题
* 对于本题而言当needle是空字符串时我们应当返回 0 这与 C 语言的strstr()以及 Java 的indexOf()定义相符
* @Version: 1.0
*/
public class StrStr {
@Test
public void test() {
String haystack = "hello";
String needle = "ll";
int i = strStr(haystack, needle);
System.out.println(i);
}
@Test
public void test1() {
String haystack = "aaaaa";
String needle = "bba";
int i = strStr(haystack, needle);
System.out.println(i);
}
@Test
public void test2() {
String haystack = "baabbbbababbbabab";
String needle = "abbab";
int i = strStr(haystack, needle);
System.out.println(i);
}
@Test
public void test3() {
String haystack = "ababaabbbbababbaabaaabaabbaaaabbabaabbbbbbabbaabbabbbabbbbbaaabaababbbaabbbabbbaabbbbaaabbababbabbbabaaabbaabbabababbbaaaaaaababbabaababaabbbbaaabbbabb";
String needle = "abbabbbabaa";
int i = strStr(haystack, needle);
System.out.println(i);
}
@Test
public void test4() {
String haystack = "ababac";
// String needle = "abbabbbabaa";
int[] next = getNext1(haystack);
System.out.println(Arrays.toString(next));
}
/**
* 尝试使用KMP算法:维护一个next数组,存储needle的最小前缀和最小后缀匹配的长度,从而减少从头开始匹配的次数,从而将时间复杂度从O(n*m)降到O(n+m)
* 具体内容参考代码随想录和数据结构与算法之美的讲解内容
* 速度击败39.11%内存击败91.79%
*
* @param haystack
* @param needle
* @return
*/
public int strStr(String haystack, String needle) {
int[] next = getNext(needle);
int j = 0;
for (int i = 0; i < haystack.length(); ++i) {
while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
j = next[j - 1] + 1;
}
if (haystack.charAt(i) == needle.charAt(j)) {
++j;
}
if (j == needle.length()) {
return i - j + 1;
}
}
return -1;
}
public int[] getNext(String needle) {
int[] result = new int[needle.length()];
for (int i = 0; i < needle.length(); i++) {
result[i] = -1;
if (i == 0) {
continue;
}
int right = i;
for (int left = i - 1; left >= 0; left--) {
boolean flag = false;
if (needle.charAt(left) == needle.charAt(right)) {
flag = true;
for (int z = left - 1, k = right - 1; z >= 0; z--, k--) {
if (needle.charAt(z) != needle.charAt(k)) {
flag = false;
break;
}
}
}
if (flag) {
result[i] = left;
break;
}
}
}
return result;
}
/**
* 官方获取next数组的方法精髓在于这次的next[i]可以通过上一次的next[i-1]来获取分为两种情况
* 1如果next[i-1]的下一个数和next[i]的下一个数相等那么最大子串一定是在上一个的基础上+1,对应下面的if的内容
* 2如果next[i-1]的下一个数和next[i]的下一个数不相等那么寻找上一个最大子串看看上一次最大子串的下一个数和next[i]的下一个数相等如果不相等就寻找在上一次的对应于下面的while内容
* 下所述的看就是用来记录上一次最大子串的索引
*
* 速度击败39.11%内存击败73.88%
* 但是只用了1ms
* @param needle
* @return
*/
public int[] getNext1(String needle) {
int[] next = new int[needle.length()];
next[0] = -1;
int k = -1;
for (int i = 1; i < needle.length(); ++i) {
while (k != -1 && needle.charAt(k + 1) != needle.charAt(i)) {
k = next[k];
}
if (needle.charAt(k + 1) == needle.charAt(i)) {
++k;
}
next[i] = k;
}
return next;
}
}