思路讲解与算法实现 LeetCode - 实现 strStr()

举报
陈皮的JavaLib 发表于 2021/06/09 22:33:55 2021/06/09
【摘要】 每天一道公司算法真题,讲解解题思路与各种算法实现;欢迎大家点评或者说出你的解题想法,或评论想让我讲解哪道题! 目录 题目思路算法实现上下篇 题目 实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返...

每天一道公司算法真题,讲解解题思路与各种算法实现;欢迎大家点评或者说出你的解题想法,或评论想让我讲解哪道题!

题目

实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。当 needle空字符串 时我们应当返回 0

示例1:

  • 输入: haystack = “hello”, needle = “ll”
  • 输出:2

示例2:

  • 输入:haystack = “aaaaa”, needle = “bba”
  • 输出:-1

示例3:

  • 输入:haystack = “aaaaa”, needle = “”
  • 输出:0

思路

字符串匹配,最简单的,无非暴力匹配,但这效率是最低的。

如果不自己实现,现有很多api都实现了此功能,例如StringindexOf方法就能达到此效果。

但是此题目是让我们自己实现,说到字符串匹配问题,最有名的无非是KMP算法

KMP算法核心思想是用模式串(即本题目的needle)构建一个next数组

  • next数组各值的含义:代表当前字符之前的字符串中,有多大长度的相同前缀
  • 例如如果next[j]=k,代表j之前的字符串中有最大长度为k的相同前缀。
  • 意味着在某个字符失配时,该字符对应的next值会告诉你下一步匹配中,模式串应该跳到哪个位置(跳到next[j]的位置)。
  • 如果next[j]等于0,则跳到模式串的开头字符,若next[j]=k且k>0,代表下次匹配跳到j之前的某个字符,而不是跳到开头,即跳过了k个字符。

算法实现

package com.nobody;

/**
 * @Description 实现 strStr() 函数。 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle
 * 字符串出现的第一个位置(从0开始)。如果不存在,则返回  -1。
 *
 * @Author Mr.nobody
 * @Date 2021/1/23
 * @Version 1.0
 */
public class StrStr { public static int strStr(String haystack, String needle) { // 文本串长度小于模式串,明显匹配不到 if (haystack.length() < needle.length()) { return -1; } // 利用KMP算法构建next数组 int[] next = buildNext(needle); int i = 0, j = 0; while (i < haystack.length() && j < needle.length()) { if (haystack.charAt(i) == needle.charAt(j)) { // 匹配,两个下标都向后 j++; i++; } else if (j == 0) { // 开头处匹配失效 i++; } else { // 利用KMP,回溯到具体位置 j = next[j]; } } return j == needle.length() ? i - j : -1; } // KMP算法 // next数组各值的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀。 // 例如如果next[j]=k,代表j之前的字符串中有最大长度为k的相同前缀后缀。 // 意味着在某个字符失配时,该字符对应的next值会告诉你下一步匹配中,模式串应该跳到哪个位置(跳到next[j]的位置)。 // 如果next[j]等于0,则跳到模式串的开头字符,若next[j]=k且k>0,代表下次匹配跳到j之前的某个字符,而不是跳到开头,即跳过了k个字符。 private static int[] buildNext(String needle) { // 记录模式串needle每个字符匹配失效后应该回溯的位置,即nextArr[j]为在j处匹配失效后,下一个匹配(回溯)的位置, int[] next = new int[needle.length()]; int j; // 因为第0个字符匹配失效,肯定还是从0个字符开始,所以i的从1开始 for (int i = 1; i < needle.length(); i++) { j = i - 1; while (j > 0 && needle.charAt(i - 1) != needle.charAt(next[j])) { j = next[j]; } if (j <= 0) { next[i] = 0; } else { next[i] = next[j] + 1; } } return next; } public static void main(String[] args) { System.out.println(strStr("hello", "ll")); System.out.println(strStr("aaaaa", "bba")); System.out.println(strStr("aaaaa", "")); }
}

  
 

输出结果:

2
-1
0

  
 

Leetcode执行结果:
在这里插入图片描述

上下篇

上一篇思路讲解与算法实现 LeetCode - 数组形式的整数加法

下一篇思路讲解与算法实现 LeetCode - 判定字符是否唯一

文章来源: javalib.blog.csdn.net,作者:陈皮的JavaLib,版权归原作者所有,如需转载,请联系作者。

原文链接:javalib.blog.csdn.net/article/details/113064532

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。