代码随想录算法训练营第9天

编程入门 行业动态 更新时间:2024-10-09 23:22:27

代码随想录<a href=https://www.elefans.com/category/jswz/34/1770096.html style=算法训练营第9天"/>

代码随想录算法训练营第9天

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 仅由小写英文字符组成

教程:.%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((n−m+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(m∗n),n为haystack的长度,m为needle的长度

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

class Solution {public int strStr(String haystack, String needle) {int m = needle.length();// 当 needle 是空字符串时我们应当返回 0if (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 由小写英文字母组成

教程:.%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;}
}

更多推荐

代码随想录算法训练营第9天

本文发布于:2023-11-17 12:07:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1644021.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:算法   训练营   代码   随想录

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!