代码随想录刷题-字符串-实现 strStr()
Posted 夏日 の blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码随想录刷题-字符串-实现 strStr()相关的知识,希望对你有一定的参考价值。
文章目录
实现 strStr()
本节对应代码随想录中:代码随想录,讲解视频:帮你把KMP算法学个通透!(理论篇)_哔哩哔哩_bilibili、帮你把KMP算法学个通透!(求next数组代码篇)_哔哩哔哩_bilibili
习题
题目链接:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
示例 1:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
暴力解法
题目意思是 needle 字符串是否在 haystack 字符串中出现,如果出现返回第一次出现的位置
那么直观的解法就是遍历 haystack 字符串,不断地将当前字符串与 needle 第一个字符比较,如果相同,则再依次比较后续长度的元素是否还是等于 needle 对应位置的元素。需要注意的是遍历 haystack 字符串的边界条件是 i+needle.size()<=haystack.size()
,因为一旦剩余的 haystack 字符串小于 needle 的长度,那肯定无法匹配,避免 haystack[i+j]
可能出现数组越界的情况
class Solution
public:
int strStr(string haystack, string needle)
int n = haystack.size(), m = needle.size();
// 循环遍历haystack,i表示当前检查的位置
for (int i = 0; i + m <= n; i++)
bool flag = true;
// 循环遍历needle字符串的每个字符
for (int j = 0; j < m; j++)
if (haystack[i + j] != needle[j])
// 如果在某个字符处匹配失败,则标记flag为false,跳出循环
flag = false;
break;
if (flag) // 如果整个needle字符串都匹配上了,返回起始位置i
return i;
return -1;// 如果找不到needle字符串,返回-1
;
- 时间复杂度:O( m ∗ n m*n m∗n)。通过两层循环实现字符串匹配,外层循环的次数是 n - m + 1(其中n是haystack的长度,m是needle的长度),内层循环的次数是needle的长度m。因此,该算法的时间复杂度为 O(nm)
- 空间复杂度:O( 1 1 1)。用了常量级别的额外存储空间,因为只使用了几个整型变量和两个字符串形参,不随着输入数据量的变化而变化。因此,该算法的空间复杂度为 O(1)
kmp 解法
这道题主要还是考察 kmp。上面的暴力解法,一旦不匹配我们是向后移动一位再尝试匹配,而 kmp 则优化了这个移动的过程,向后移动更多位来提高效率。简单来讲,如下图,kmp 是将公共前后缀的前缀移到了后缀的位置而不是像①一样只移动一位位置。
关于 kmp 的理论,建议先看这个视频:【天勤考研】KMP算法易懂版_哔哩哔哩_bilibili,了解下原理。再去看代码随想录的视频熟悉代码该怎么写。
那么每次不匹配的时候该移动多少呢,这就涉及到 next 数组的构建。在进行字符串匹配的时候,我们先构建 next 数组用来记录每个位置的公共前后缀长度,之后当不匹配的时候直接根据 next 数组进行移动。
class Solution
public:
// 获取next数组,用于字符串匹配
void getNext(int* next, const string& s)
// ①初始化next数组第一个值为0
int j = 0;
next[0] = 0;
// 循环遍历s中每个字符
for(int i = 1; i < s.size(); i++)
// ②前后缀不相同
while (j > 0 && s[i] != s[j])
j = next[j - 1]; //若匹配失败则回溯到之前的状态继续匹配
// ③前后缀相同
if (s[i] == s[j]) //若当前字符和目标匹配
j++; //将匹配数量+1
// ④更新next数组
next[i] = j; //将新的匹配数量重新赋值至next数组
// 实现字符串匹配算法
int strStr(string haystack, string needle)
int next[needle.size()];
getNext(next, needle); //获取needle字符串的next数组
int j = 0; //j代表子串needle中已经匹配到的字符个数
// 循环遍历haystack中的每个字符
for (int i = 0; i < haystack.size(); i++)
while(j > 0 && haystack[i] != needle[j])
j = next[j - 1]; //回溯,将j移动到目前匹配的最长公共前后缀的结尾处
if (haystack[i] == needle[j]) //如果当前字符匹配成功
j++; //继续匹配下一个字符
if (j == needle.size() ) //如果匹配成功,返回子串在字符串中的位置
return (i - needle.size() + 1);
return -1; //匹配失败,返回-1
;
- 时间复杂度:O( m + n m+n m+n)。其中 m 和 n 分别为 haystack 和 needle 字符串的长度。在 strStr 函数中,有一个 while 循环嵌套在 for 循环中,循环次数最多为 haystack 字符串长度 m 加上 needle 字符串长度 n,所以时间复杂度为 O(m+n)
- 空间复杂度:O( n n n)。定义了一个 int 数组 next,其长度为 needle 字符串长度 n,所以空间复杂度为 O(n)
Leetcode刷题100天—28. 实现 strStr()( 滑动窗口)—day91
前言:
作者:神的孩子在歌唱
一个算法小菜鸡
大家好,我叫智
28. 实现 strStr()
难度简单1166
实现 strStr() 函数。
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1
。
说明:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
示例 1:
输入:haystack = "hello", needle = "ll"
输出:2
示例 2:
输入:haystack = "aaaaa", needle = "bba"
输出:-1
示例 3:
输入:haystack = "", needle = ""
输出:0
提示:
0 <= haystack.length, needle.length <= 5 * 104
haystack
和needle
仅由小写英文字符组成
class Solution
// 滑动窗口
public int strStr(String haystack, String needle)
int neelen=needle.length();
int haylen=haystack.length();
if(neelen==0)
return 0;
if(haylen<neelen)
return -1;
int hayneelen=haylen-neelen;
for(int i=0;i<=hayneelen;i++)
int right=needle.length();
int pivot=0;
int left=i;
while(right>0)
if(haystack.charAt(left)!=needle.charAt(pivot))
break;
left++;
right--;
pivot++;
if(right==0)
return i;
return -1;
本人csdn博客:https://blog.csdn.net/weixin_46654114
转载说明:跟我说明,务必注明来源,附带本人博客连接。
以上是关于代码随想录刷题-字符串-实现 strStr()的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode刷题100天—28. 实现 strStr()( 滑动窗口)—day91
Leetcode刷题100天—28. 实现 strStr()( 滑动窗口)—day91