今日学习的文章链接和视频链接
https://programmercarl.com/0028.%E5%AE%9E%E7%8E%B0strStr.html
LeetCode28.实现strStr()
链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/
1.思路
思路一:两个字符串对象A,B,判断是否A包含B关系。首先判断长度是否满足A>=B,满足则进行继续判断。一个for循环实现对A字符串的遍历,判断首字母是否相同,相同则截取与B字符串等长的A字符串的子串,再来一层for循环遍历判断两字符串是否相同。
思路二:
2.代码实现
1// 思路一:自己实现运行没通过,思路没问题,应该是边界问题??
2class Solution {
3 public int strStr(String haystack, String needle) {
4 int h = haystack.length();
5 int n = needle.length();
6 for (int i = 0; i < h; i++) {
7 if (h < n) {
8 return -1;
9 } else {
10 if (haystack.charAt(i) == needle.charAt(i)) {
11 // 截取子字符串sub.h
12 if (i + n >= h) {
13 return -1;
14
15 } else {
16 String sub = haystack.substring(i, i + n);
17 // 遍历子字符串
18 int count = 0;
19 for (int j = 0; j < n; j++) {
20 if (needle.charAt(j) != sub.charAt(i)) {
21 break;
22 } else {
23 count++;
24 }
25 }
26 if (count == n) {
27 return i;
28 }
29 }
30
31 }
32 }
33
34 }
35
36 return -1;
37 }
38}
39
40// 思路一修正:精简!
41class Solution {
42 public int strStr(String haystack, String needle) {
43 int n = haystack.length(), m = needle.length();
44 for (int i = 0; i + m <= n; i++) { // 原数组边界判定非常巧妙!!!
45 boolean flag = true; // 巧妙的判定方式,get!
46 for (int j = 0; j < m; j++) {
47 if (haystack.charAt(i + j) != needle.charAt(j)) {
48 flag = false;
49 break;
50 }
51 }
52 if (flag) {
53 return i;
54 }
55 }
56 return -1;
57 }
58}
59
60// KMP算法抄了一遍
61class Solution {
62 //前缀表(不减一)Java实现
63 public int strStr(String haystack, String needle) {
64 if (needle.length() == 0) return 0;
65 int[] next = new int[needle.length()];
66 getNext(next, needle);
67
68 int j = 0;
69 for (int i = 0; i < haystack.length(); i++) {
70 while (j > 0 && needle.charAt(j) != haystack.charAt(i))
71 j = next[j - 1];
72 if (needle.charAt(j) == haystack.charAt(i))
73 j++;
74 if (j == needle.length())
75 return i - needle.length() + 1;
76 }
77 return -1;
78
79 }
80
81 private void getNext(int[] next, String s) {
82 int j = 0;
83 next[0] = 0;
84 for (int i = 1; i < s.length(); i++) {
85 while (j > 0 && s.charAt(j) != s.charAt(i))
86 j = next[j - 1];
87 if (s.charAt(j) == s.charAt(i))
88 j++;
89 next[i] = j;
90 }
91 }
92}
3.复杂度分析
字符串haystack和字符串needle的长度分别是m和n,显然数据量上看,其时间复杂度为O(m * n)
时间复杂度为O(1)
4.思考总结
双层for暴力解决;
滑动窗口处理边界问题容易产生漏洞;
KMP算法的实现逻辑有点抽象,主要是构造next数组的实现细节。
LeetCode459.重复的子字符串
链接:
https://leetcode.cn/problems/repeated-substring-pattern/solution/
1.思路
思路一:for循环遍历,判断是重复段及其段数,对每段再进行滑动窗口的遍历。
2.代码实现
1// 自己实现,嵌套过多,导致逻辑不清晰。
2class Solution {
3 public boolean repeatedSubstringPattern(String s) {
4 // for循环遍历
5 int fastIndex = 0;
6 int SlowIndex = 0;
7 for (int i = 0; i < s.length(); i++) {
8 while (s.charAt(SlowIndex) != s.charAt(fastIndex)) {
9 fastIndex++;
10 }
11 // 相等则进行遍历比较
12 int n = fastIndex;
13 if (s.length() % n != 0) {
14 return false;
15 } else {
16 int m = s.length() / n;
17 boolean bln = true;
18 for (int j = m; j < s.length(); j + m) {
19
20 if (s.charAt(j - m) != s.charAt(j)) {
21 return -1;
22 }
23 }
24 if (bln) {
25 return ture;
26 }
27 }
28
29 }
30 return false;
31
32
33 }
34}
35
36// 修正思路
37class Solution {
38 public boolean repeatedSubstringPattern(String s) {
39 int n = s.length();
40 // 遍历所有可能的子串长度
41 for (int i = 1; i * 2 <= n; i++) {
42 // 如果字符串长度能够整除当前子串长度
43 if (n % i == 0) {
44 boolean match = true;
45 // 检查从第 i 个字符开始的每个字符是否与前面的子串相等
46 for (int j = i; j < n; j++) {
47 if (s.charAt(j) != s.charAt(j - i)) {
48 match = false;
49 break;
50 }
51 }
52 // 如果所有字符都与前面的子串相等,则返回 true
53 if (match) {
54 return true;
55 }
56 }
57 }
58 // 如果没有找到重复的子串,则返回 false
59 return false;
60 }
61}
3.复杂度分析
时间复杂度:O(n²)
空间复杂度:O(1)(不确定)
字符串总结
1.存储形式类似于数组,可以通过索引进行遍历
2.字符串常见问题:
字符串反转:双指针法
字符串包含及重复子串问题:循环遍历(KMP算法进行优化)
今日收获,记录一下自己的学习时长
3h