代码随想录算法训练营第9天|28. 找出字符串中第一个匹配项的下标 459. 重复的子字符串

JAVA代码编写

28. 找出字符串中第一个匹配项的下标

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:

输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

提示:

  • 1 <= haystack.length, needle.length <= 104

  • haystackneedle 仅由小写英文字符组成

教程:https://programmercarl.com/0028.%E5%AE%9E%E7%8E%B0strStr.html

方法一:暴力

思路:如果needle字符串长度大于haystack的,返回-1.

两个for循环,默认初始flag为true,i为匹配字符串的起始位置,j为匹配字符串的终止位置,遍历的时候比较每个字符串是否相等,有不等的就设置flag为false,停止循环,更新i,再进行变量。

复杂度分析

  • 时间复杂度: O ( ( n − m + 1 ) ∗ m ) O((n-m+1)*m) O((nm+1)m)

  • 空间复杂度: O ( 1 ) O(1) O(1)

class Solution {
    public int strStr(String haystack, String needle) {
    int n = haystack.length();
    int m = needle.length();
    if (m > n) return -1;
    for (int i = 0; i <= n - m; i++) {
        boolean flag = true;
        for (int j = 0; j < m; j++) {
            if (haystack.charAt(i + j) != needle.charAt(j)) {
                flag = false;
                break;
            }
        }
        if (flag) return i;
    }
    return -1;
    }
}

原谅我知道用两层for循环,但是代码细节部分还是会出错,有时整debug还老半天

方法二:基于窗口滑动的算法

思路:这个和for循环有点像,这里的i是在haystack中找到第一个和needle一样的字符,然后再比较i之后的字符串和needle是否相同。

复杂度分析

  • 时间复杂度: O ( m ∗ n ) O(m*n) O(mn),n为haystack的长度,m为needle的长度

  • 空间复杂度: O ( 1 ) O(1) O(1)

class Solution {
    public int strStr(String haystack, String needle) {
        int m = needle.length();
        // 当 needle 是空字符串时我们应当返回 0
        if (m == 0) {
            return 0;
        }
        int n = haystack.length();
        if (n < m) {
            return -1;
        }
        int i = 0;
        int j = 0;
        while (i < n - m + 1) {
            // 找到首字母相等
            while (i < n && haystack.charAt(i) != needle.charAt(j)) {
                i++;
            }
            if (i == n) {// 没有首字母相等的
                return -1;
            }
            // 遍历后续字符,判断是否相等
            i++;
            j++;
            while (i < n && j < m && haystack.charAt(i) == needle.charAt(j)) {
                i++;
                j++;
            }
            if (j == m) {// 找到
                return i - j;//这里可以返回i-m,我觉写i-m更好理解一点,这里i遍历完,是在haystack中最后一个字符且和needle匹配的索引,索引要知道起始索引,减去要匹配字符串的长度m即可
            } else {// 未找到
                i -= j - 1;//等价于i=i-j+1,也就是起始位置右移了一下
                j = 0;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        Solution s = new Solution();
        s.strStr("aasadbutsad","sad");
    }
}

方法三:KMP

KMP基础

KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。

备考软件设计师的时候遇到过KMP,只是会做选择题,没懂。

next数组就是一个前缀表(prefix table)。前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配

要在文本串:aabaabaafa 中查找是否出现过一个模式串:aabaaf。

459. 重复的子字符串

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

教程:https://programmercarl.com/0459.%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2.html

方法一:KMP

思路

复杂度分析

  • 时间复杂度: O ( l e n ) O(len) O(len)

  • 空间复杂度: O ( l e n ) O(len) O(len),len是字符串的长度

class Solution {
    public boolean repeatedSubstringPattern(String s) {
                if (s.equals("")) return false;

        int len = s.length();
        // 原串加个空格(哨兵),使下标从1开始,这样j从0开始,也不用初始化了
        s = " " + s;
        char[] chars = s.toCharArray();
        int[] next = new int[len + 1];

        // 构造 next 数组过程,j从0开始(空格),i从2开始
        for (int i = 2, j = 0; i <= len; i++) {
            // 匹配不成功,j回到前一位置 next 数组所对应的值
            while (j > 0 && chars[i] != chars[j + 1]) j = next[j];
            // 匹配成功,j往后移
            if (chars[i] == chars[j + 1]) j++;
            // 更新 next 数组的值
            next[i] = j;
        }

        // 最后判断是否是重复的子字符串,这里 next[len] 即代表next数组末尾的值
        if (next[len] > 0 && len % (len - next[len]) == 0) {
            return true;
        }
        return false;
    }
}

你可能感兴趣的:(leetcode,代码随想录,算法,算法)