LeetCode 实现 strStr() 题解(暴力匹配法)

题目描述

实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从 0 开始)。如果不存在,则返回 -1。

说明:当 needle 是空字符串时,我们应当返回 0。这与 C 语言的strstr() 以及 Java 的 indexOf() 定义一致。

解题思路

核心思路:暴力匹配法

以字符串 haystack 的每一个字符为起点,逐一与字符串 needle 的字符进行对比。若从某个起点开始,能完整匹配 needle 的所有字符,则直接返回该起点索引;若遍历完haystack 仍无完整匹配,返回 -1。

复杂度分析

  • 时间复杂度O((n-m) \\times m),其中 nhaystack 长度,mneedle 长度。最坏情况下,需遍历 haystackn-m+1 个起点,每个起点需对比 m 个字符。

  • 空间复杂度O(1),仅使用有限个变量存储索引和长度,不额外占用存储空间。

解题代码

java 复制代码
class Solution {
    public int strStr(String haystack, String needle) {
        if ("".equals(needle)) {
            return 0;
        }

        int len1 = haystack.length();
        int len2 = needle.length();
        int p = 0;
        int q = 0;
        while (p < len1) {
            if (haystack.charAt(p) == needle.charAt(q)) {
                if (len2 == 1) {
                    return p;
                }
                ++p;
                ++q;
            } else {
                p -= q - 1;
                q = 0;
            }

            if (q == len2) {
                return p - q;
            }
        }
        return -1;
    }
}

代码解析

边界处理

首先判断 needle 是否为空字符串,若为空则直接返回 0,符合题目定义及主流语言的 API 行为。

指针逻辑

  1. 定义两个指针 p(遍历 haystack)和 q(遍历 needle),初始均为 0。

  2. haystack[p]needle[q] 匹配时,双指针同时加 1,继续对比下一个字符。

  3. 当字符不匹配时,p 回退到"上一轮匹配开始位置的下一位"(即 p -= q - 1),q 重置为 0,重新开始匹配。

  4. q 等于 needle 长度时,说明已完整匹配,此时匹配起点为 p - q(因为 p 已遍历完匹配的所有字符),直接返回该索引。

特殊优化

needle 长度为 1 时,一旦找到匹配字符可直接返回当前 p,避免后续无意义的指针移动,小幅提升效率。

测试案例

案例 1:常规匹配

输入:haystack = "hello", needle = "ll" 输出:2 解析:从索引 2 开始,"ll" 与 haystack 子串完全匹配。

案例 2:无匹配项

输入:haystack = "aaaaa", needle = "bba" 输出:-1 解析:遍历完 haystack 无对应子串,返回 -1。

案例 3:needle 为空

输入:haystack = "anystring", needle = "" 输出:0 解析:空字符串按规则返回 0。

案例 4:needle 长度为 1

输入:haystack = "abc", needle = "c" 输出:2 解析:触发特殊优化,匹配后直接返回当前索引。

进阶思考

暴力匹配法思路简单、实现容易,但时间复杂度较高,在大规模字符串匹配场景下效率不佳。更高效的算法可参考 KMP 算法 ,通过预处理 needle 构建部分匹配表,将时间复杂度优化至 O(n+m),空间复杂度为 O(m)。后续将单独整理 KMP 算法的实现与解析。

总结

本题暴力匹配法是入门级解法,适合理解字符串匹配的核心逻辑,代码简洁且无额外空间开销,能应对 LeetCode 本题的所有测试用例。在实际开发中,若字符串规模较小,暴力法足够高效;若需处理大规模数据,建议采用 KMP、Boyer-Moore 等优化算法。

相关推荐
六义义2 小时前
java基础十二
java·数据结构·算法
四维碎片3 小时前
QSettings + INI 笔记
笔记·qt·算法
Tansmjs3 小时前
C++与GPU计算(CUDA)
开发语言·c++·算法
独自破碎E3 小时前
【优先级队列】主持人调度(二)
算法
weixin_445476684 小时前
leetCode每日一题——边反转的最小成本
算法·leetcode·职场和发展
打工的小王4 小时前
LeetCode Hot100(一)二分查找
算法·leetcode·职场和发展
Swift社区4 小时前
LeetCode 385 迷你语法分析器
算法·leetcode·职场和发展
sonadorje4 小时前
svd在图像处理中的应用
算法
挖矿大亨4 小时前
c++中的函数模版
java·c++·算法
测试老哥4 小时前
软件测试之功能测试详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例