今天的每日一题是道设计题,不是很喜欢这种题目,复现太费事了。这里把思路理清了我就没写了,先埋个坑,以后有时间补上。看到时间O(1)就知道一定是用HashMap的,然后LRU的删除机制需要把数据动态更新,这样用双向链表最好,每次get或者put的时候都放到头节点上,如果超出容量,就删除双向链表的尾节点。
思路想出来没用多久,然后刚好把之前KMP的坑给埋了。
题目:
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例1:
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例2:
输入: haystack = "aaaaa", needle = "bba"
输出: -1
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
这是道简单题,很容易想到双指针一起走来对比,不过想都不用想效率肯定低,但是KMP算法就不好理解,当初是似懂非懂,今天看了几个博客和视频终于懂了。
个人感觉这个视频讲的很好:https://www.bilibili.com/video/BV1Ys411d7yh
KMP核心思想是抓住子串的自相似性,减少遍历过程中重复对比的次数。即计算子串needle每一个位置之前的字符串的前缀和后缀公共部分的最大长度(不包括字符串本身,否则最大长度始终是字符串本身)。获得每一个位置的最大公共长度之后,就可以利用该最大公共长度快速和字符串haystack比较。当每次比较到两个字符串的字符不同时,我们就可以根据最大公共长度将子串needle向前移动(已匹配长度-最大公共长度)位,接着继续比较下一个位置。
代码复现的时候和视频有所不同,视频中数组下标从1开始,C的下标从0开始
int* getNext(char* needle){
int lenOfneedle=strlen(needle);
int* next=(int *) malloc(sizeof(int)*lenOfneedle);
next[0] = -1;
int j = 0, k = -1;
while(j<lenOfneedle - 1){
if(k == -1 || needle[k] == needle[j]){
j++;
k++;
next[j] = k;
}
else
k = next[k];
}
return next;
}
int strStr(char* haystack, char* needle){
int lenOfhaystack=strlen(haystack),lenOfneedle=strlen(needle);
if(lenOfneedle==0)
return 0;
int* next = getNext(needle);
int i=0,j=0;
while(i < lenOfhaystack && (j <lenOfneedle)){
if(j == -1 || haystack[i] == needle[j]){
i++;
j++;
}
else
j = next[j];
}
if(j == lenOfneedle)
return i-j;
return -1;
}
运行结果: