【JavaScript】【KMP】Leetcode每日一题-实现strStr()
【JavaScript】Leetcode每日一题-实现strStr()
【题目描述】
实现 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 * 10^4
haystack 和 needle 仅由小写英文字符组成
【分析】
暴力搜索:
顾名思义,直接暴力搜索匹配即可。
代码:
var strStr = function(haystack, needle) {
var nlen = needle.length;
var hlen = haystack.length;
for(var i=0;i <= hlen - nlen;i++){
if(haystack.slice(i, i+nlen) == needle){
return i;
}
}
return -1;
};

Sunday解法:
参考:Sunday题解
重点:
代码:
var strStr = function(haystack, needle) {
var hash = {};
var nlen = needle.length;
var hlen = haystack.length;
for(var i='a';i <= "z";){
hash[i] = nlen;
i = String.fromCharCode(i.charCodeAt() + 1);
}
for(var i in needle){
hash[needle[i]] = nlen - i;
}
var index = 0;
for(var i=0;i <= hlen - nlen;){
if(haystack.slice(i, i+nlen) == needle){
return i;
}
else{
i += hash[haystack[i+nlen]];
}
}
return -1;
};

KMP:

思路:
暴力过程中,原串i每次位移一位,且当不匹配时,i会回溯到匹配起始位置,而我们的KMP则是保证i不会回溯,在不匹配位置继续向前匹配,实现则需要一个对模式串预处理得到的next数组,数组表示
不匹配位置向前移动j(已进行匹配操作长度、当前模式串索引值)后回跳的位数,比如可以参见上图理解,例如,第5位不匹配,则可以直接向后位移5位,再回跳2位。
或者可以理解成,将next[j]位置移到不匹配位置,例如,当第5位匹配出错时,将第二位即b移到当前不匹配位置。
则此时两个a刚好匹配上,而i可以从不匹配位置继续向前走,匹配过程由于i不回溯,时间复杂度为\(O(n)\)。
next数组构建过程算是KMP精妙之处吧!
const next = new Array(m+1).fill(0); //默认第一位不用,方便计算
let i = 1, j = 0;
while (i < m) {
if (j == 0 || needle[i-1] == needle[j-1])
{++i; ++j; next[i] = j;}
else j = next[j]; //回调j直到j=0或needle[i]=needle[j]
} //对着示例想一遍就明白了
因此,时间复杂度为\(O(n+m)\)。
var strStr = function(haystack, needle) {
const n = haystack.length, m = needle.length;
if (m === 0) {
return 0;
}
const next = new Array(m+1).fill(0);
let i = 1, j = 0;
while (i < m) {
if (j == 0 || needle[i-1] == needle[j-1]){
++i; ++j; next[i] = j;
}
else{
j = next[j];
}
}
for (let i = 0, j = 0; i < n; i++) {
while (j > 0 && haystack[i] != needle[j]) {
j = next[j + 1] - 1;
}
if (haystack[i] == needle[j]) {
j++;
}
if (j === m) {
return i - m + 1;
}
}
return -1;
};

KMP优化:

如图,next数组有时候效果并不理想,于是增添nextval数组记录最佳偏移。
var strStr = function(haystack, needle) {
const n = haystack.length, m = needle.length;
if (m === 0) {
return 0;
}
// const next = new Array(m+1).fill(0);
const nextval = new Array(m+1).fill(0);
let i = 1, j = 0;
while (i < m) {
if (j == 0 || needle[i-1] == needle[j-1])
{++i; ++j;
if(needle[i-1] != needle[j-1]){
nextval[i] = j;
}
else{
nextval[i] = nextval[j];
}
}
else j = nextval[j];
}
for (let i = 0, j = 0; i < n; i++) {
while (j > 0 && haystack[i] != needle[j]) {
j = nextval[j + 1] == 0 ? 0 : nextval[j + 1] - 1;
}
if (haystack[i] == needle[j]) {
j++;
}
if (j === m) {
return i - m + 1;
}
}
return -1;
};

内置函数(离谱
var strStr = function(haystack, needle) {
return haystack.indexOf(needle);
};

【JavaScript】【KMP】Leetcode每日一题-实现strStr()的更多相关文章
- 【JavaScript】Leetcode每日一题-在D天内送包裹的能力
[JavaScript]Leetcode每日一题-在D天内送包裹的能力 [题目描述] 传送带上的包裹必须在 D 天内从一个港口运送到另一个港口. 传送带上的第 i 个包裹的重量为 weights[i] ...
- 【JavaScript】Leetcode每日一题-青蛙过河
[JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...
- 【JavaScript】Leetcode每日一题-平方数之和
[JavaScript]Leetcode每日一题-平方数之和 [题目描述] 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c . 示例1: 输入:c = 5 ...
- 【JavaScript】Leetcode每日一题-二叉搜索树的范围和
[JavaScript]Leetcode每日一题-二叉搜索树的范围和 [题目描述] 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例1: 输入: ...
- 【JavaScript】Leetcode每日一题-递增顺序搜索树
[JavaScript]Leetcode每日一题-递增顺序搜索树 [题目描述] 给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没 ...
- 【JavaScript】Leetcode每日一题-组合总和4
[JavaScript]Leetcode每日一题-组合总和4 [题目描述] 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target .请你从 nums 中找出并返回总和为 targ ...
- 【JavaScript】Leetcode每日一题-最大整除子集
[JavaScript]Leetcode每日一题-最大整除子集 [题目描述] 给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对(an ...
- 【JavaScript】Leetcode每日一题-矩形区域不超过K的最大值和
[JavaScript]Leetcode每日一题-矩形区域不超过K的最大值和 [题目描述] 给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大 ...
- 【JavaScript】Leetcode每日一题-移除元素
[JavaScript]Leetcode每日一题-移除元素 [题目描述] 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用 ...
随机推荐
- Celery:小试牛刀
Celery是如何工作的? Celery 由于 其分布式体系结构,在某种程度上可能难以理解.下图是典型Django-Celery设置的高级示意图(FROM O'REILLY): 当请求到达时,您可以在 ...
- P3369 【模板】普通平衡树 题解(Splay/FHQ)
题目链接 P3369 [模板]普通平衡树 解题思路1:Splay 注意查询的时候大于小于等于号千万不要搞错了:注意适时伸展 AC代码1 #include<stdio.h> #define ...
- Typora的一些快捷键
语法格式 快捷键 标题 # + 空格 = 一级标题, ## + 空格 =二级标题, 以此类推 shift + 数字1 =一级标题 ,shift + 数字2 =二级标题 , 以此类推 有序列表 1 ...
- c语言链表从本地文件中读取和写入数据
1 typedef struct Data{ 2 40 char *name; 3 41 char *IDCARD; 4 42 char *job_id; 5 43 char *length; 6 4 ...
- Stone Game, Why are you always there? HDU - 2999
题目链接:https://vjudge.net/problem/HDU-2999 题意:有N堆石头,两个人交替取,每次只能取连续的k个石子,最后没有石子取得人输. 思路:如果我们每次取靠边的k个,那么 ...
- Git本地仓库基本操作-1
code[class*="language-"], pre[class*="language-"] { color: rgba(51, 51, 51, 1); ...
- node_exporter自定义监控
背景 我们在使用Zabbix的时候,可以自己写自定义脚本.在使用Promethues的时候,有很多的exporter,但是有一些特殊的情况没有,比如,我需要监控进程一启动就告警,但是进程没启动,是使用 ...
- 基于Hive进行数仓建设的资源元数据信息统计:Spark篇
在数据仓库建设中,元数据管理是非常重要的环节之一.根据Kimball的数据仓库理论,可以将元数据分为这三类: 技术元数据,如表的存储结构结构.文件的路径 业务元数据,如血缘关系.业务的归属 过程元数据 ...
- [Fundamental of Power Electronics]-PART I-5.不连续导电模式-5.4 总结与重点
5.4 总结与重点 基本的buck,boost以及buck-boost电路的特点总结在表5.2中.其中给出了\(K_{crit}(D)\)的表达式,CCM和DCM下的变换比,以及DCM下二极管导通占空 ...
- 宝塔linux7.4.2/windows6.8 的版本中的安全随笔
在2020/8.23宝塔官方发布了一条关于宝塔linux7.4.2和Windows6.8版本中存在的重大的安全隐患 通知来源https://www.bt.cn/bbs/thread-54644-1-1 ...