算法(TS): 实现 strStr()

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

解答

遍历 haystack,当 haystack[i] === needle[0]时,再比较 haystack[i + 1] 与 needle[1]是否相等,haystack[i + 2] 与 needle[2] 是否相等,一直到 haystack[i + needle.length - 1] 与 needle[needle.length - 1] 是否相等。这个过程一共有两层遍历,当 haystack[i] === needle[0] 满足时,才开始第二层遍历

ini 复制代码
function strStr(haystack: string, needle: string): number {
    let index = -1
    let i = 0
    while(i < haystack.length) {
        if (haystack[i] === needle[0]) {
            let step = 1
            let isInclude = true
            while(step < needle.length) {
                if (haystack[i + step] !== needle[step]) {
                    isInclude = false
                    break
                }
                step++
            }

            if (isInclude) {
                index = i
                break
            }
        }

        i++
    }

    return index
};

空间复杂度O(1),时间负责度O(m * n)

needle 是 haystack 的一部分,意味着 haystack 的长度不小于 needle 的长度,因此对上面的解答进行优化

ini 复制代码
function strStr(haystack: string, needle: string): number {
    let index = -1
    let i = 0
    while(i < haystack.length) {
        if (haystack.length - i < needle.length) {
            break
        }
        if (haystack[i] === needle[0]) {
            let step = 1
            let isInclude = true
            while(step < needle.length) {
                if (haystack[i + step] !== needle[step]) {
                    isInclude = false
                    break
                }
                step++
            }

            if (isInclude) {
                index = i
                break
            }
        }

        i++
    }

    return index
};

在上述解法中,每一次遇到不匹配的位置都是将 needle 往后移动一步,利用KMP算法计算出部分匹配表,动态计算需要移动的步数

ini 复制代码
function strStr(haystack: string, needle: string): number {
    const n = haystack.length, m = needle.length;
    let index = -1
    let i = 0
    // 部分匹配表
    const pi = new Array(m).fill(0);
    for (let i = 1, j = 0; i < m; i++) {
        while (j > 0 && needle[i] !== needle[j]) {
            j = pi[j - 1];
        }
        if (needle[i] == needle[j]) {
            j++;
        }
        pi[i] = j;
    }

    while(i < n) {
        let j = 1
        if (n - i < m) {
            break
        }
        if (haystack[i] === needle[0]) {
            let step = 1
            let isInclude = true
            while(step < m) {
                if (haystack[i + step] !== needle[step]) {
                    isInclude = false
                    // needle 移动步数 = 已匹配的字符数 - 对应的部分匹配值
                    j = step - pi[step-1]
                    break
                }
                step++
            }

            if (isInclude) {
                index = i
                break
            }
        }

        i += j
    }

    return index
};

时间复杂度O(m+n),空间复杂度O(m)

相关推荐
聚客AI17 分钟前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v3 小时前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工5 小时前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农6 小时前
【React用到的一些算法】游标和栈
算法·react.js
烛阴6 小时前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
博笙困了6 小时前
AcWing学习——双指针算法
c++·算法
moonlifesudo7 小时前
322:零钱兑换(三种方法)
算法
NAGNIP1 天前
大模型框架性能优化策略:延迟、吞吐量与成本权衡
算法
奔跑的蜗牛ing1 天前
Vue3 + Element Plus 输入框省略号插件:零侵入式全局解决方案
vue.js·typescript·前端工程化
美团技术团队1 天前
LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
人工智能·算法