【力扣算法20】之 8. 找出字符串中第一个匹配项的下标 (python方向)

简介: 【力扣算法20】之 8. 找出字符串中第一个匹配项的下标 (python方向)

问题描述


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

思路分析

在解决这个问题时,可以采用双指针的思路。首先,我们将两个指针分别指向 haystackneedle 的起始位置。然后,我们开始遍历 haystack 字符串,比较当前指针位置处的字符是否与 needle 字符串中的字符相同。如果相同,我们就继续比较下一个字符,直到完全匹配或者遍历完了 needle 字符串。

步骤如下:

  1. needle 是空字符串,则返回下标 0。
  2. 计算 haystackneedle 的长度,分别记为 nm
  3. haystack 的第一个字符开始遍历,遍历范围为 n - m + 1
  4. 对于每个位置 i,使用指针 j 遍历 needle ,并比较 haystack[i+j]needle[j] 的字符是否相等。如果相等,继续比较下一个字符;如果不相等,跳出循环。
  5. 如果 j 遍历到了 needle 的末尾,即 j == m,说明找到了第一个匹配项,返回当前指针 i 的值减去 needle 的长度 m
  6. 如果遍历完了 haystack 还没有找到匹配项,则返回 -1,表示 needle 不是 haystack 的一部分。

这样,我们就可以找到字符串 needle 在字符串 haystack 中的第一个匹配项的下标。


代码分析


  1. 首先,检查特殊情况,如果 needle 是空字符串,则直接返回下标 0,因为空字符串是任意字符串的子串。
  2. 计算 haystackneedle 的长度,分别赋值给变量 nm。这样做是为了避免在循环中多次访问 len() 函数。
  3. 使用外层循环 for i in range(n - m + 1) 遍历 haystack 的每个可能的起始位置。注意,外层循环的范围是 n - m + 1,因为当剩余的字符数小于 needle 的长度时,自然无法匹配。
  4. 在内层循环 for j in range(m) 中,使用指针 j 遍历 needle 的每个字符,并与 haystack 中对应位置的字符进行比较。如果字符相等,则继续比较下一个字符;如果字符不相等,则退出内层循环。
  5. 如果内层循环正常结束,即 j 遍历到了 needle 的末尾,说明找到了第一个匹配项,可以返回当前指针 i 的值。
  6. 如果外层循环结束后还没有找到匹配项,则返回 -1,表示 needle 不是 haystack 的子串。

这种算法的思路是逐个比较字符,直到找到匹配项或遍历完整个 haystack。在最坏情况下(没有匹配项或者匹配项在最后一个起始位置),需要进行大约 (n - m + 1) * m 次字符比较操作。


完整代码


class Solution(object):
  def strStr(self, haystack, needle):
      if not needle:  # 特殊情况判断:needle为空字符串
          return 0
      n = len(haystack)  # haystack长度
      m = len(needle)  # needle长度
      for i in range(n - m + 1):  # 遍历haystack的每个起始位置
          for j in range(m):  # 遍历needle的每个字符
              if haystack[i+j] != needle[j]:  # 当前字符不匹配,跳出内层循环
                  break
          else:
              return i  # 内层循环正常结束,找到匹配项,返回当前指针i的值
      return -1  # 未找到匹配项,返回-1

详细分析


class Solution(object):
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        ""

这段代码定义了一个名为 Solution 的类,并在类中定义了一个名为 strStr 的方法。strStr 方法接受两个参数 haystackneedle,它们分别表示被搜索的字符串和待搜索的子字符串。方法的返回类型声明为 int

if not needle:
            return 0

这段代码首先检查特殊情况,即如果 needle 是空字符串,则直接返回 0。因为空字符串是任何字符串的子串。

n = len(haystack)
        m = len(needle)

这段代码使用 len() 函数获取字符串 haystackneedle 的长度,并将它们分别存储在变量 nm 中。这样做是为了避免在后续循环中多次调用 len() 函数,从而提高效率。

for i in range(n - m + 1):
            j = 0
            while j < m and haystack[i+j] == needle[j]:
                j += 1
            if j == m:
                return i

这段代码使用两个循环来实现字符串的匹配。外层循环使用 for 循环遍历 haystack 中每个可能的起始位置,范围是 n - m + 1。因为当剩余的字符数少于 needle 的长度时,无法进行匹配。

内层循环使用 while 循环,通过比较 haystack 中的字符和 needle 中的字符来进行匹配。循环条件为 j < m and haystack[i+j] == needle[j],表示当指针 j 小于 needle 的长度并且当前字符匹配时,继续循环。

如果内层循环正常结束,并且指针 j 的值等于 m,即遍历完了整个 needle,说明找到了匹配的子串,返回当前指针 i 的值。

return -1

如果外层循环结束后仍然没有找到匹配项,则说明 needle 不是 haystack 的子串,返回 -1。


运行效果截图


调用示例


solution = Solution()
haystack = "sadbutsad"
needle = "sad"
haystack1 = "leetcode"
needle1 = "leeto"
print(solution.strStr(haystack, needle))
print(solution.strStr(haystack1, needle1))

运行结果


完结


相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
10天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
41 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
10天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
36 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
10天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
50 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
15天前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
|
15天前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
32 2
|
1月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
63 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
1月前
|
算法
两个字符串匹配出最长公共子序列算法
本文介绍了最长公共子序列(LCS)问题的算法实现,通过动态规划方法求解两个字符串的最长公共子序列,并提供了具体的编程实现细节和示例。
85 1
两个字符串匹配出最长公共子序列算法
|
27天前
|
机器学习/深度学习 人工智能 算法
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
车辆车型识别,使用Python作为主要编程语言,通过收集多种车辆车型图像数据集,然后基于TensorFlow搭建卷积网络算法模型,并对数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django搭建web网页端操作界面,实现用户上传一张车辆图片识别其类型。
72 0
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
|
1月前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
下一篇
无影云桌面