今日学习的文章链接和视频链接
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