LeetCode 28. 找出字符串中第一个匹配项的下标

文章目录

  • 一、题目
  • 二、C# 题解

一、题目

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

二、C# 题解

  题目直接调用库函数即可。这里复习一下 KMP 算法,首先构造 next 数组。注意,next 数组长度为 needle + 1。采取这样的做法是为了使后缀指针 j 不会指向 -1,这里 next[0] 的位置就充当了 next[-1] 的位置,以免数组越界报错。
  为什么 j 一定要指向 -1 呢,不可以指向 0 就停止回退吗?不行,因为 j 指向 0 时,无法区分 j 此时是回退到 0(此时 j 不应该 + 1,因为下一次还要指向第一个字符,即 j = 0),还是指前后缀的最后一位相等(此时 j 应该 + 1,下一次 j = 1)。
  正因 next 数组长度为 needle + 1,else j = next[j + 1] - 1; 该段代码需要对 j 先 + 1,取出 next 值后再 -1。完整代码如下:

public class Solution {public int StrStr(string haystack, string needle) {int[] next = GetNext(needle); // 获取 next 数组int i = 0, j = 0;             // i 指向 haystack,j 指向 needlewhile (i < haystack.Length) {// j 回退到 -1 或字符相同,则进行下一位匹配if (j == -1 || haystack[i] == needle[j]) { i++; j++; }else j = next[j + 1] - 1;             // 否则,j 依据 next 数组回退if (j == needle.Length) return i - j; // j 遍历完 needle,返回 needle 起始位置}return -1;}// 获取 next 数组public int[] GetNext(string needle) {int[] next = new int[needle.Length + 1]; // next 长度为 needle + 1,next[0] 空着,作用是避免 j 越界next[1] = 0;                             // next[1,n] 存储 needle 对应的字符下标int i = 1, j = 0;                        // i 指向 needle[0,i] 后缀末尾,j 指向 needle[0,i] 前缀末尾while (i < needle.Length) {// j 回退到 0 或后缀相同,则 i、j 一同前进,并给 next 赋值if (j == 0 || needle[i - 1] == needle[j - 1]) next[++i] = ++j;else j = next[j]; // 否则,j 回退}return next;}
}
  • 时间复杂度: O ( m + n ) O(m+n) O(m+n),其中, m m mhaystack 长度,n 为 needle 长度。
  • 空间复杂度: O ( n ) O(n) O(n)

  《大话数据结构》中提到了 KMP 的优化,改动为 GetNext 函数中的如下代码,即加了一行判断处理。下面对改代码做出简略解释:

            // j 回退到 0 或后缀相同,则 i、j 一同前进,并给 next 赋值if (j == 0 || needle[i - 1] == needle[j - 1]) if (needle[i] == needle[j]) next[++i] = next[++j];else next[++i] = ++j;else j = next[j]; // 否则,j 回退

  即判断前后缀后一个字符是否相同。如果相同,直接将之前的 next 结果复制过来;否则,按照之前的处理即可。下面举例说明这样做的正确性,图中,黑色箭头表示 i,红色箭头表示 j。

在这里插入图片描述
  可以看到,最后一位不相同,按照原本的规则,next[6] 应取 3(绿色箭头指向位置,从 1 开始计数)。但是由于前缀和后缀都是 ab,且其后一位均为 e。因此将 next[6] 赋值为 next[3],即 next[6] = next[3] = 1。
在这里插入图片描述
  为什么可以这样呢,因为 next[6] 是 e,已经不匹配了,那么跳到相同字符的 next[3] 处也一定不匹配,因此直接跳到 next[next[3]](蓝色箭头指向位置)就好啦!完整代码如下:

public class Solution {public int StrStr(string haystack, string needle) {int[] next = GetNext(needle); // 获取 next 数组int i = 0, j = 0;             // i 指向 haystack,j 指向 needlewhile (i < haystack.Length) {// j 回退到 -1 或字符相同,则进行下一位匹配if (j == -1 || haystack[i] == needle[j]) { i++; j++; }else j = next[j + 1] - 1;             // 否则,j 依据 next 数组回退if (j == needle.Length) return i - j; // j 遍历完 needle,返回 needle 起始位置}return -1;}// 获取 next 数组public int[] GetNext(string needle) {int[] next = new int[needle.Length + 1]; // next 长度为 needle + 1,next[0] 空着,作用是避免 j 越界next[1] = 0;                             // next[1,n] 存储 needle 对应的字符下标int i = 1, j = 0;                        // i 指向 needle[0,i] 后缀末尾,j 指向 needle[0,i] 前缀末尾while (i < needle.Length) {// j 回退到 0 或后缀相同,则 i、j 一同前进,并给 next 赋值if (j == 0 || needle[i - 1] == needle[j - 1]) {if (needle[i] == needle[j]) next[++i] = next[++j];else next[++i] = ++j;}else j = next[j]; // 否则,j 回退}return next;}
}
  • 时间复杂度: O ( m + n ) O(m+n) O(m+n)
  • 空间复杂度: O ( n ) O(n) O(n)

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

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

相关文章

Java 内存模型(JMM)

1.概述 JMM&#xff0c;全称 Java Memory Model&#xff0c;中文释义Java内存模型 对于 Java 程序员来说&#xff0c;在虚拟机自动内存管理机制下&#xff0c;不再需要像C/C程序开发程序员那样为每一个 new 操作去写对应的 delete/free操作&#xff0c;不容易出现内存泄漏和内…

LeetCode 2596. 检查骑士巡视方案【数组,模拟】1448

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

LeetCode 53. 最大子数组和

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 使用动态规划的方法进行解决&#xff0c;我们创建一个dp表&#xff0c;用来记录以该下标为结尾的最大子数组。然后每次存dp表的时候&#xff0c;进行取最大值。最终返回最大值。 由…

二叉排序树(BST)的算法分析以及基本操作(结点的查询,插入,删除)

1.二叉排序树的定义 二叉排序树&#xff0c;又称二叉查找树&#xff08;BST&#xff0c;Binary Search Tree) 默认不允许两个结点的关键字相同。 1.二叉排序树的性质: 任意一棵二叉排序树的子树的结点大小都满足“左小右大”。 左子树上所有结点的关键字均小于根结点的关键…

基于Python和mysql开发的智慧校园答题考试系统(源码+数据库+程序配置说明书+程序使用说明书)

一、项目简介 本项目是一套基于Python和mysql开发的智慧校园答题考试系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都…

【动手学深度学习】--长短期记忆网络LSTM

文章目录 长短期记忆网络LSTM1.门控记忆元1.1输入门、忘记门、输出门1.2候选记忆元1.3记忆元1.4隐状态 2.从零实现2.1加载数据集2.2初始化模型参数2.3定义模型2.4 训练与预测 3.简洁实现 长短期记忆网络LSTM 学习视频&#xff1a;长短期记忆网络&#xff08;LSTM&#xff09;【…

白鲸开源 X SelectDB 金融大数据联合解决方案公布!从源头解决大数据开发挑战

业务挑战与痛点 随着互联网技术的发展、云计算技术的成熟、人工智能技术的兴起和数字化经济的崛起&#xff0c;数据已成为企业的核心资产。在金融行业中&#xff0c;数字化已成为了支撑各类业务场景的核心力量&#xff0c;包括个人理财、企业融资、股票交易、保险理赔、贷款服…

TensorFlow 02(张量)

一、张量 张量Tensor 张量是一个多维数组。与NumPy ndarray对象类似&#xff0c;tf.Tensor对象也具有数据类型和形状。如下图所示: 此外&#xff0c;tf.Tensors可以保留在GPU中。TensorFlow提供了丰富的操作库 (tf.add&#xff0c;tf.matmul,tf.linalg.inv等)&#xff0c;它们…

文字点选验证码识别(下)-训练一个孪生神经网络模型

声明 本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 如有侵权,请联系我进行删除。 文章中没有代码,只有过程思路,请大家谨慎订阅。…

HarmonyOS Codelab 优秀样例——溪村小镇(ArkTS)

一、介绍 溪村小镇是一款展示溪流背坡村园区风貌的应用&#xff0c;包括园区内的导航功能&#xff0c;小火车行车状态查看&#xff0c;以及各区域的风景展览介绍&#xff0c;主要用于展示HarmonyOS的ArkUI能力和动画效果。具体包括如下功能&#xff1a; 打开应用时进入启动页&a…

哪种IP更适合你的数据抓取需求?

程序员大佬们好&#xff01;今天我要和大家分享一个关于数据抓取的话题&#xff0c;那就是Socks5爬虫ip和动态IP之间的比较。在进行数据抓取时&#xff0c;选择适合自己需求的工具和技术是非常重要的。Socks5爬虫ip和动态IP都是常见的网络工具&#xff0c;它们在数据抓取方面都…

Spring Boot 中的参数验证和自定义响应处理,使用 @Valid 注解

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; Spring Boot 中的参数验证和自定义响应处理&#xff0c;使用 Valid 注解…

【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)

<template><div :class"$options.name"><div class"sg-head">接口代码生成工具</div><div class"sg-container"><div class"sg-start "><div style"margin-bottom: 10px;">接口地…

做期权卖方一般会怎么选择合约?

我们知道期权有多种获利方式&#xff0c;其中靠时间能赚钱的是做期权卖方策略&#xff0c;虽然赚得慢&#xff0c;但可以稳稳地收入权利金&#xff0c;适合某些稳健风格的投资者&#xff0c;胜率对比买方也是高了很多&#xff0c;那么做期权卖方一般会怎么选择合约&#xff1f;…

LeetCode(力扣)45. 跳跃游戏 IIPython

LeetCode45. 跳跃游戏 II 题目链接代码 题目链接 https://leetcode.cn/problems/jump-game-ii/description/ 代码 class Solution:def jump(self, nums: List[int]) -> int:if len(nums) 1:return 0curdis 0nextdis 0step 0for i in range(len(nums)):nextdis max(…

华为云耀云服务器HECS安装Docker

先去购买服务器&#xff0c;这里就不多说了 1、进入自己买的服务器&#xff0c; 找到切换系统 2、选择centOs镜像 安装docker 卸载旧版本 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序&#xff0c;请卸载它们以及相关的依赖项。 yum remove docker…

职业规划就问它!海量知识与智慧,AIGC助你冲破择业迷茫

数字化时代的兴起改变了我们的日常生活和职业工作方式。科技迅猛的发展&#xff0c;尤其是人工智能的崛起&#xff0c;将我们引入了一个崭新的智能化时代。在这个时代中&#xff0c;AI被认为是从"数字时代"向"数智时代"转变的关键元素&#xff0c;引领着这…

2023年Gartner新技术与AI成熟度曲线

1. Gartner 将生成式 AI 置于 2023 年新技术成熟度曲线的顶峰&#xff0c;新兴人工智能将对商业和社会产生深远影响 根据 Gartner, Inc. 2023 年新兴技术成熟度曲线&#xff0c;生成式人工智能 (AI) 处于成熟度曲线期望的顶峰&#xff0c;预计将在两到五年内实现转型效益。生成…

htaccess绕过上传实验

实验目的 利用上传htaccess文件解析漏洞绕过验证进行上传PHP脚本木马 实验工具 火狐&#xff1a;Mozilla Firefox&#xff0c;中文俗称“火狐”&#xff08;正式缩写为Fx或fx&#xff0c;非正式缩写为FF&#xff09;&#xff0c;是一个自由及开放源代码网页浏览器&#xff0…

Linux OpenGauss 数据库远程连接

目录 前言 1. Linux 安装 openGauss 2. Linux 安装cpolar 3. 创建openGauss主节点端口号公网地址 4. 远程连接openGauss 5. 固定连接TCP公网地址 6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行。openGauss内…