【力扣】28.找出字符串中第一个匹配项的下标|每日一题|刷题打卡

100 阅读2分钟

一、题目描述

给你两个字符串 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 仅由小写英文字符组成

二、思路分析

  1. 使用双指针的方式 iji 用来遍历 haystack 字符串,j 用来匹配 needle 字符串

  2. 边界判断:检查 needle 的长度,如果为 0,则直接返回 0,因为空字符串是任何字符串的子串

  3. 遍历 haystack 字符串

  4. 匹配判断:

    • 比较 haystack 与 needle 是否匹配,如果匹配,则让两个指针都++,直到当 j 等于 needleLen - 1,说明已经找到了完整的匹配子串,返回当前匹配子串的起始索引 i - j
    • 如果不匹配,则 i 需要回到上一次匹配的位置,然后 +1,从上次匹配的位置的下一个位置开始;j 需要重置为 0,重新从 needle 的开头开始匹配
  5. 最后如果不匹配返回 -1

这里的 i - j + 1不好理解:实际就是一旦发现不匹配了,不能草率的直接让 i++,需要有一个回溯的过程,所以需要回到上一次匹配的位置,然后 +1 从下一个位置开始,进行后续的匹配(参考测试4进行理解)

三、代码答案

/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
var strStr = function (haystack, needle) {
  const haystackLen = haystack.length;
  const needleLen = needle.length;
  if (needleLen === 0) return 0;
  let i = 0;
  let j = 0;
  while (i < haystackLen) {
    // 判断是否相等
    if (haystack[i] === needle[j]) {
      if (j === needleLen - 1) return i - j;
      i++;
      j++;
    } else {
      // i-j:将 i 移动到上一个匹配的位置
      i = i - j + 1;
      // 重置
      j = 0;
    }
  }
  return -1
};

// 测试1
console.log(strStr("hello", "ll")); // 2
// 测试2
console.log(strStr("sadbutsad", "sad")); // 0
// 测试3
console.log(strStr("leetcode", "leeto")); // -1
// 测试4
console.log(strStr("mississippi", "issip")); // 4