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

文章目录

  • 问题描述
    • 示例1
    • 示例2
    • 提示
  • 思路分析
  • 代码分析
  • 完整代码
  • 详细分析
  • 运行效果截图
    • 调用示例
    • 运行结果
  • 完结

问题描述

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

给你两个字符串 haystack needle ,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是haystack的一部分,则返回 -1

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

示例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 仅由小写英文字符组成

思路分析

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

在解决这个问题时,可以采用双指针的思路。首先,我们将两个指针分别指向 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 中的第一个匹配项的下标。

代码分析

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

  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 次字符比较操作。

完整代码

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

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))

运行结果

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

完结

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

你可能感兴趣的:(力扣刷题记录,算法,leetcode,python,字符串匹配,循环,python面试题)