Leetcode第28题:实现 strStr()【python】

 作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

问题描述

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

说明:

  • needle 是空字符串时,我们应返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
示例

输入: haystack = "hello", needle = "ll"

输出: 2

输入: haystack = "aaaaa", needle = "bba"

输出: -1

解题思路

实现 strStr() 函数的方法多种多样,包括暴力匹配法、KMP算法、Rabin-Karp 算法等。下面分别简述这些方法:

1. 暴力匹配法

暴力匹配法是最直接的方法,它遍历 haystack 中的每个子串,检查子串是否与 needle 相等。

算法步骤
  • 遍历从 0len(haystack) - len(needle) 的每一个起始位置。
  • 对每一个起始位置,比较后续的 len(needle) 个字符是否与 needle 相等。
代码实现

这里提供暴力匹配法的实现:

def strStr(haystack: str, needle: str) -> int:"""实现 strStr() 函数。Args:haystack (str): 主字符串,从中搜索子字符串。needle (str): 子字符串,需要在主字符串中找到其第一次出现的位置。Returns:int: 子字符串在主字符串中第一次出现的索引;如果不存在,则返回 -1。"""# 特殊情况处理if not needle:return 0if not haystack:return -1# 获取主字符串和子字符串的长度L, n = len(needle), len(haystack)# 只在主字符串长度减去子字符串长度的范围内搜索for start in range(n - L + 1):# 检查从start开始的长度为L的子串是否等于needleif haystack[start:start + L] == needle:return startreturn -1# 调用函数示例
haystack = "hello"
needle = "ll"
print(strStr(haystack, needle))  # 输出: 2haystack = "aaaaa"
needle = "bba"
print(strStr(haystack, needle))  # 输出: -1
复杂度分析:
  • 时间复杂度:O((N-M)M),其中 N 是 haystack 的长度,M 是 needle 的长度。
  • 空间复杂度:O(1)。
2. KMP 算法(Knuth-Morris-Pratt)
算法步骤

KMP算法的核心思想是当发生不匹配时,能够利用已匹配的部分信息,确定模式串的哪个部分应该重新进行匹配,从而避免从头开始匹配。

构建前缀表

  • 前缀表记录了模式串中每个位置之前的子串的前缀与后缀的最长共有元素的长度。
  • 这个表用于在发生不匹配时,确定模式串应该回溯到哪个位置重新开始匹配。

搜索过程

  • 使用前缀表来调整模式串的位置,减少不必要的比较。
  • 当发生不匹配时,根据前缀表中记录的值调整模式串的位置。
代码实现
def kmp_search(haystack: str, needle: str) -> int:"""实现 KMP 算法进行字符串搜索。Args:haystack (str): 主字符串,从中搜索子字符串。needle (str): 子字符串,需要在主字符串中找到其第一次出现的位置。Returns:int: 子字符串在主字符串中第一次出现的索引;如果不存在,则返回 -1。"""if not needle:return 0if not haystack:return -1# 构建前缀表lps = build_lps(needle)i = j = 0  # i 是 haystack 的指针,j 是 needle 的指针while i < len(haystack):if haystack[i] == needle[j]:i += 1j += 1if j == len(needle):return i - jelif j > 0:j = lps[j - 1]else:i += 1return -1def build_lps(needle: str) -> list:"""构建前缀表 (Longest Prefix which is also Suffix table) 用于 KMP 算法。Args:needle (str): 需要构建前缀表的字符串。Returns:list: 前缀表。"""lps = [0] * len(needle)length = 0  # 最长前缀后缀的长度i = 1       # lps[0] 是 0,从 lps[1] 开始填充表while i < len(needle):if needle[i] == needle[length]:length += 1lps[i] = lengthi += 1else:if length != 0:length = lps[length - 1]else:lps[i] = 0i += 1return lps# 调用函数示例
haystack = "hello"
needle = "ll"
print(kmp_search(haystack, needle))  # 输出: 2haystack = "aaaaa"
needle = "bba"
print(kmp_search(haystack, needle))  # 输出: -1
复杂度分析
  • 时间复杂度:O(N+M),预处理时间为 O(M),匹配时间为 O(N)。
  • 空间复杂度:O(M)。
3. Rabin-Karp 算法

Rabin-Karp 算法是一种高效的字符串搜索算法,特别适用于多模式搜索。它通过计算字符串的哈希值来快速筛选可能的匹配,从而避免在每一步都进行详细的字符比较。

算法步骤

哈希函数

  • 选择一个合适的哈希函数来计算字符串的哈希值。常用的方法是将字符串视为一个大的数值,计算它模一个大素数的值。

计算 needle 的哈希值

  • 计算模式串(needle)的哈希值。

计算 haystack 子串的哈希值并比较

  • 逐步计算主字符串(haystack)中每个长度与 needle 相等的子串的哈希值。
  • 如果哈希值匹配,则进行进一步的字符比较以确认完全匹配。

滚动哈希

  • 为了有效计算连续子串的哈希值,使用滚动哈希技术,根据前一个哈希值快速计算下一个哈希值。
def rabin_karp_search(haystack: str, needle: str) -> int:"""实现 Rabin-Karp 算法进行字符串搜索。Args:haystack (str): 主字符串,从中搜索子字符串。needle (str): 子字符串,需要在主字符串中找到其第一次出现的位置。Returns:int: 子字符串在主字符串中第一次出现的索引;如果不存在,则返回 -1。"""M, N = len(needle), len(haystack)if M > N:return -1if not needle:return 0# 基数和模块数(大素数以减少冲突)base, mod = 256, 997# 计算needle的哈希值和第一个窗口的哈希值hash_needle, hash_window = 0, 0for i in range(M):hash_needle = (hash_needle * base + ord(needle[i])) % modhash_window = (hash_window * base + ord(haystack[i])) % mod# 如果只有一个字符,直接比较初值if hash_needle == hash_window:if haystack[:M] == needle:return 0# 预计算base^(M-1) % modpower_base = 1for i in range(M - 1):power_base = (power_base * base) % mod# 滚动哈希:遍历剩余的窗口for i in range(1, N - M + 1):hash_window = (hash_window * base - ord(haystack[i - 1]) * power_base + ord(haystack[i + M - 1])) % modif hash_window < 0:hash_window += modif hash_window == hash_needle:# 验证实际字符串是否匹配if haystack[i:i + M] == needle:return ireturn -1# 调用函数示例
haystack = "hello"
needle = "ll"
print(rabin_karp_search(haystack, needle))  # 输出: 2haystack = "aaaaa"
needle = "bba"
print(rabin_karp_search(haystack, needle))  # 输出: -1
复杂度分析:
  • 平均时间复杂度:O(N+M)。
  • 最坏情况下的时间复杂度:O(NM),当所有哈希值都冲突时。
  • 空间复杂度:O(1)。

总结

下面是对暴力匹配法、KMP算法、以及Rabin-Karp算法在实现 strStr() 函数时的优势、劣势及其时间复杂度和空间复杂度的对比表格,这将帮助在不同场景下选择最适合的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/615171.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#生成一个绿色文件

生成一个绿色文件免去了安装的繁琐过程&#xff0c;直接运行&#xff0c;非常方便。 新建一个类库项目 在类库Class1中实现简单的Sum方法。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespac…

【Hello算法】 > 第 2 关 >数据结构 之 数组与链表

数据结构 之 数组与链表 1&#xff1a;Understanding data structures &#xff01;——了解数据结构——1.1&#xff1a;Classification-分类-1.2&#xff1a;Type-类型- 2&#xff1a;Arrays are the bricks that make up the wall of data structures *——数组是组成数据结…

二、Maven安装

Maven安装 一、Centos7.9安装1.下载2.安装3.设置国内镜像4.设置maven安装路径 一、Centos7.9安装 1.下载 第一种&#xff1a;官网下载最新版本&#xff1a;http://maven.apache.org/download.cgi第二种&#xff1a;其他版本下载&#xff1a;https://archive.apache.org/dist/…

Ubuntu20.04安装和编译运行lidar_align来联合标定lidar与imu的外参

硬件&#xff1a;树霉派4b、天眸lidar(32线)、IMU(GNSS不接天线) 系统&#xff1a;ubuntu20.04、 天眸lidar(32线)&#xff1a; IMU(GNSS不接天线)&#xff1a; 1、下载并安装lidar_align mkdir -p lidar_align/src cd lidar_align/src git clone https://github.com/ethz-…

RK3568平台 SPI设备驱动

一.SPI简介 SPI是许多不同设备使用的常见通信协议。例如&#xff0c;SD卡模块、RFID读卡器模块和2.4GHz无线发射机/接收器均使用SPI与微控制器进行通信。 SPI是串行外设接口&#xff08;Serial Peripheral Interface)的缩写&#xff0c;是一种高速的&#xff0c;全双工&#x…

Elastic 线下 Meetup 将于 2024 年 4 月 27 号在重庆举办

2024 Elastic Meetup 重庆站活动&#xff0c;由 Elastic、新智锦绣联合举办&#xff0c;现诚邀广大技术爱好者及开发者参加。 活动时间 2024年4月27日 13:30-18:00 活动地点 中国重庆 沙坪坝区学城大道62-1号研发楼一期b3栋1楼(瑞幸咖啡旁&#xff09; 活动流程 14:00-14:50…

如何恢复未保存或删除/丢失的Word文件?

关闭 Word 应用程序而不保存文档&#xff1f;误删Word文档&#xff1f;许多用户会在不同的情况下丢失Word文档。如果不幸遇到此类问题&#xff0c;如何恢复已删除或未保存的 Word 文档&#xff1f;有一些方法可以恢复未保存/删除的文档。此外&#xff0c;您还可以使用Word文件恢…

基于Springboot的二手交易平台

基于SpringbootVue的二手交易平台的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录页 首页 商品信息 商品求购 网站公告 留言反馈 个人中心 后台管理 后台首页 用户…

卫星遥感影像在农业方面的应用及评价

一、引言 随着科技的进步&#xff0c;卫星遥感技术在农业领域的应用越来越广泛。卫星遥感技术以其宏观、快速、准确的特点&#xff0c;为农业生产和管理提供了有力的技术支撑。本文将对卫星遥感在农业方面的应用进行详细介绍&#xff0c;并通过具体案例进行说明。 二、…

算法题解记录10+++缺失的第一个正数

题目描述&#xff1a; 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 […

初识ansible服务及ansible主机清单配置

目录 1、什么是自动化批量管理 2、自动化工具ansible架构 3、ansible服务专用术语对照表 4、设置主机清单&#xff08;inventory&#xff09; 3.1实验环境准备 3.2配置主机清单 3.2.1分组基本格式 3.2.2指定用户名&#xff0c;密码。端口 3.2.3子组 3.3查看 3.3.1看…

Pandas部分应掌握的重要知识点

目录 Pandas部分应掌握的重要知识点一、DataFrame数据框的创建1、直接基于二维数据创建&#xff08;同时使用index和columns参数&#xff09;2、基于excel文件中的数据来创建 二、查看数据框中的数据和联机帮助信息1、查看特殊行的数据2、查看联机帮助的两种常见方法&#xff0…