算法练习-Day3-找出字符串中第一个匹配项的下标

144 阅读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. 这是我之前学python时写的:
class Solution:
    def strStr(self, haystack, needle):
        """
        实现字符串查找功能(手动实现)
        
        参数:
            haystack: str - 主字符串
            needle: str - 要查找的子串
            
        返回:
            int - 子串首次出现的索引,未找到返回-1
        """
        # 遍历所有可能的起始位置
        for i in range(0, len(haystack) - len(needle) + 1):
            # 检查当前窗口是否匹配needle
            if haystack[i:i+len(needle)] == needle:
                return i  # 找到匹配,返回当前索引
        return -1  # 遍历结束未找到匹配
  1. 这是我用JavaScript写的,这个不能说是算法,平常开发的时候可以这么写
/**
 * 实现字符串查找功能(使用内置方法)
 * @param {string} haystack - 主字符串
 * @param {string} needle - 要查找的子串
 * @return {number} - 子串首次出现的索引,未找到返回-1
 */
var strStr = function(haystack, needle) {
    // 直接调用JavaScript内置的字符串查找方法
    return haystack.indexOf(needle);
};

关键区别说明:

Python实现:

  • 手动实现字符串匹配逻辑
  • 使用切片(haystack[i:i+len(needle)])进行子串比较
  • 时间复杂度: O((n-m)*m),其中n是haystack长度,m是needle长度
  • 空间复杂度: O(1)

JavaScript实现:

  • 直接调用语言内置的indexOf方法
  • 引擎底层通常使用优化算法实现
  • 时间复杂度: 通常为O(n),具体取决于浏览器实现
  • 空间复杂度: O(1) """
  1. 用JavaScript代码写滑动窗口实现 ❌
/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
var strStr = function(haystack, needle) {
    // return haystack.indexOf(needle)
    for (let i = 0; i < needle.length; i++) {
        if (i + needle.length > haystack.length) break
        // 这个判断会让第一次不匹配就立即返回-1
        if (haystack.slice(i, i + needle.length) === needle) {
            return i
        } else {
            return -1
        }
    }
};
  1. JavaScript滑动窗口实现 ✅
var strStr = function(haystack, needle) {
    // 处理边界情况
    if (needle.length === 0) return 0;
    if (haystack.length < needle.length) return -1;
    
    // 主循环
    for (let i = 0; i <= haystack.length - needle.length; i++) {
        // 检查当前窗口是否匹配
        let match = true;
        for (let j = 0; j < needle.length; j++) {
            if (haystack[i + j] !== needle[j]) {
                match = false;
                break;
            }
        }
        if (match) return i;
    }
    
    return -1;
};