【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 的元素,并返回移除后数组的新长度. 不要使用 ...
随机推荐
- vue全家桶和react全家桶
vue全家桶:vue + vuex (状态管理) + vue-router (路由) + vue-resource +axios +elementui react全家桶 : react + re ...
- Java系列教程-SpringMVC教程
SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...
- 使用python的虚拟环境virtualenv
技术背景 在前面几篇博客中我们介绍了容器的使用(博客1.博客2.博客3.博客4.博客5),容器是一种系统级的隔离方案,更多的强调资源上的隔离.而这里我们要介绍的python的虚拟环境,更加强调的是依赖 ...
- 自动统计zabbix过去一周监控告警
# -*- coding:utf-8 -*-import jsonimport requestsimport time,datetimeimport csv,chardetdef getToken(u ...
- 显示IPC信息--ipcs
ipcs 显示共享内存,消息队列, 信号量全部的IPC ipcs -q ...
- 2020牛客NOIP赛前集训营-普及组(第二场)A-面试
面 试 面试 面试 题目描述 牛牛内推了好多人去牛客网参加面试,面试总共分四轮,每轮的面试官都会对面试者的发挥进行评分.评分有 A B C D 四种.如果面试者在四轮中有一次发挥被评为 D,或者两次发 ...
- Echarts概述
1. Echarts概述 ECharts是百度开源的纯 Javascript 图表库,目前开源可以与highcharts相匹敌的一个图表库.支持折线图(区域图).柱状图(条状图).散点图(气泡图).K ...
- redis的主从复制(哨兵模式)
p.p1 { margin: 0; font: 10px ".SF NS Text" } Master以写为主,Slave以读为主 读写分离 容灾恢复 一.一主多从 配置文件修改: ...
- python基础(六):列表的使用(下)
列表排序的三种方式 sort()方法:原地修改列表的排序方法 注 1:" 默认是升序" ,参数 reverse=True,表示将列表降序. 注 2:" 原地修改列表&qu ...
- 初学 Babel 工作原理
前言 Babel 对于前端开发者来说应该是很熟悉了,日常开发中基本上是离不开它的. 已经 9102 了,我们已经能够熟练地使用 es2015+ 的语法.但是对于浏览器来说,可能和它们还不够熟悉,我们得 ...