题目
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = "hello", needle = "ll"
输出: 2
示例 2:
输入: haystack = "aaaaa", needle = "bba"
输出: -1
说明:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与C语言的 strstr()
以及 Java的 indexOf()
(java.lang.String)) 定义相符。
一. 简单查找法
遍历目标字符串,每次依次从待匹配字符串头开始与当前位置及之后的位置进行比较,如果不匹配,前进一个位置重新进行匹配,如果匹配成功返回当前的位置。
如果遍历完成后仍然不匹配,则返回-1。
js实现
/**
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function(haystack, needle) {
if (!needle.length) {
return 0
}
for (var i=0;i<haystack.length;i++) {
var isEqual = true
for (var j=0;j<needle.length;j++) {
if (haystack[i+j] !== needle[j]) {
isEqual = false
break
}
}
if (isEqual) {
return i
}
}
return -1
}
复杂度分析
时间复杂度:O(mn)
空间复杂度:O(1)
测试结果
✔ Accepted
✔ 74/74 cases passed (2896 ms)
✔ Your runtime beats 10.48 % of javascript submissions
✔ Your memory usage beats 20.84 % of javascript submissions (35.2 MB)
二. Sunday算法
从前向后匹配,如果遇到不匹配的情况时,判断当前待匹配区域的最后的字符的下一位字符在模式串上最右侧的位置,然后对齐这两个位置再进行匹配,如果没有在模式串上出现则跳过此区域。
js实现
/**
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function(haystack, needle) {
// 处理边界情况
if (needle.length > haystack.length) {
return -1
}
if (!needle.length) {
return 0
}
// 计算偏移表
var offset = new Map()
for (var i=0;i<needle.length;i++) {
offset.set(needle[i], needle.length-i)
}
// 开始匹配
var index = 0
while (index + needle.length <= haystack.length) {
var isEqual = true
for (i=0;i<needle.length;i++) {
if (haystack[index+i] !== needle[i]) {
isEqual = false
break
}
}
if (isEqual) {
return index
}
var offsetValue = offset.get(haystack[index+needle.length])
if (offsetValue) {
index += offsetValue
} else {
index += needle.length + 1
}
}
return -1
}
复杂度分析
时间复杂度:O(mn)
空间复杂度:O(n)
测试结果
✔ Accepted
✔ 74/74 cases passed (72 ms)
✔ Your runtime beats 74.22 % of javascript submissions
✔ Your memory usage beats 29.64 % of javascript submissions (34.8 MB)