算法训练Day9| 28. 实现 strStr();459.重复的子字符串;字符串总结 ;双指针回顾

今日学习的文章链接和视频链接

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值