题目介绍
给你两个字符串
haystack
和needle
,请你在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
haystack
和needle
仅由小写英文字符组成
思路讲解
拿到这个问题,我们首先可以判断它是字符串匹配类型的题目,我们可以先用一个for循环遍历主字符串haystack,寻找子字符串needle可能出现的每个起始位置。然后再在内部嵌套一个for循环来逐个字符地比较在主字符串中是否找到完整匹配needle的字符串。
首先既然要遍历主字符串,并且还要寻找子字符串的位置,我们必须要求出这两个字符串的长度,才能确定for循环需要遍历几次。
int n=strlen(haystack),m=strlen(needle);
然后就要进行第一个for循环,循环变量从0开始,一直遍历到n-m,因为当主字符串的剩余长度小于子字符串的长度时,就算主字符串找到了子字符串的开头第一个元素,也不可以将子字符串完整的表示出来。
for(int i=0;i+m<=n;i++)
{
}
接着为了判断什么时候可以确认找到完整子字符串,我们定义一个bool变量,当这个bool变量经过第二个for循环而不改变,而代表经过第二个for循环的考验,已经可以确认找到了完整的子字符串,可以返回子字符串在主字符串中第一次出现的位置的索引。
bool flag=true;
接下来在第一个for循环内部在嵌套第二个for循环,当我们经过第一个for循环相当于拿到了一个钥匙,第二个for循环的目的是确认这个钥匙是不是能打开我们这个题目的门。在第二个for循环我们要从第一个for循环开始的索引位置往后判断m(子字符串的元素个数)个元素,如果从索引i开始的连续m个字符没有与needle中的所有字符一一对应相等,则说明没有找到完整的子字符串,则bool flag=false,重新进入下一次循环。
for(int j=0;j<m;j++)
{
if(haystack[i+j]!=needle[j])
{
flag=false;
break;
}
}
如果从索引i开始的连续m个字符与needle中的所有字符一一对应相等。那么说明成功找到了子字符串的起始位置,则flag不会更改,通过if语句判断flag为ture后,返回第一个for循环开始的索引位置i。
if(flag)
{
return i;
}
在第一个for循环结束后如果没有结束函数,则代表主字符串中不包含子字符串,则返回-1.
return -1;
完整代码
int strStr(char* haystack, char* needle) {
int n=strlen(haystack),m=strlen(needle);
for(int i=0;i+m<=n;i++)
{
bool flag=true;
for(int j=0;j<m;j++)
{
if(haystack[i+j]!=needle[j])
{
flag=false;
break;
}
}
if(flag)
{
return i;
}
}
return -1;
}
知识点讲解
这段代码用的是暴力匹配法:是一种简单的字符串匹配算法,它用于在主字符串中查找子字符串首次出现的位置。这种方法的基本思想是对主字符串中的每个可能的起始位置,检查子字符串是否与之匹配。使用两个嵌套的循环。外层循环遍历主字符串,内层循环遍历子字符串。在内层循环中,逐个比较主字符串和子字符串的字符。一旦发现不匹配的字符,就可以立即停止当前的内层循环,因为子字符串的字符顺序是固定的,一旦有一个字符不匹配,那么从当前主字符串位置开始的子字符串就不可能匹配。