爱写bug(ID:icodebugs)
作者:爱写bug

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1

Implement strStr().

Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

Example 1:

Input: haystack = "hello", needle = "ll"
Output: 2

Example 2:

Input: haystack = "aaaaa", needle = "bba"
Output: -1

Clarification:

What should we return when needle is an empty string? This is a great question to ask during an interview.

For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf().

说明:

needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

解题思路(Java):

  • 暴力穷举:
    ​ 复杂度:时间 O(n^2) 空间 O(1)
    ​ 字符串 a 从第一个索引开始 逐一匹配字符串 b 的第一个索引:a[i++]==b[0],如果为true,则进入内循环字符串a从第 i+j 个字符开始与字符串b 第 j个字符匹配:a[i+j]==b[j]

代码:

class Solution {public int strStr(String haystack, String needle) {if(needle.equals(""))return 0;int haystackLen=haystack.length(),needleLen=needle.length();char firstChar=needle.charAt(0);for(int i=0;i<=haystackLen-needleLen;i++){if(haystack.charAt(i)==firstChar){int j=1;for(;j<needleLen;j++){if(haystack.charAt(i+j)!=needle.charAt(j)) break;}if(j==needleLen) return i;}}return -1;}
}

  • KMP算法:
    ​ 复杂度:时间 O(n+m) 空间 O(M)
    下面引用一组图片帮助理解(图片来源:https://blog.csdn.net/v_july_v/article/details/7041827 ):
    说明: 图片中字符串haystack为:"BBC ABCDAB ABCDABCDABDE",模式串 needle 为:"ABCDABD"

第一步开始匹配:

第二步匹配到第一个相同字符:

第三步两个字符串逐一向后匹配,直到到字符 D 与 空格 字符匹配失败,结束该轮次匹配:

第四步重新匹配,但不用从第二步的下一个字符 B 开始,因为空格字符前与模式字符串前6个字符已经匹配相同。既C字符之前的两个字符 AB 与空格字符前两个字符 AB 相同,两个字符串可直接从 空白 字符与 C 字符开始匹配:

可以看到图片中一下跳过了 haystack 五个字符ABCDAB 和 needle 的两个字符AB。优化思路很清晰。

代码:

class Solution {public int strStr(String haystack, String needle) {if(needle.equals("")) return 0;int[] next = new int[needle.length()];getNext(next, needle);// 得到next数组// i是匹配串haystack的指针,j是模式串needle的指针int i = 0, j = 0;while(i < haystack.length() && j < needle.length()){// 如果j=-1,即next数组中该字符为第一位,下标+1后,重新匹配if(j == -1 || haystack.charAt(i) == needle.charAt(j)){// 如果匹配成功,则自增1,匹配下一个字符i++;j++;} else {j = next[j];// 如果匹配失败,则将j赋值next[j],避免匹配重复匹配}}return j == needle.length() ? i - j : -1;}private void getNext(int[] next, String needle){// k是前缀中相同部分的末尾,也是相同部分的长度// j是后缀的末尾,即后缀相同部分的末尾int k = -1, j = 0;next[0] = -1;while(j < needle.length() - 1){// 如果k=-1,匹配失败,重新开始计算前缀和后缀相同的长度// 如果两个字符相等,则在上次前缀和后缀相同的长度加1,继续下一段字符最大公共前后缀匹配if (k == -1 || needle.charAt(j) == needle.charAt(k)){k++;j++;if (needle.charAt(j) != needle.charAt(k))next[j] = k;else//因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]],以减少重复部分的多余匹配next[j] = next[k];} else {// 否则,前缀长度缩短为next[k]k = next[k];}}}
}

总结:

​ KMP算法优化的方向很明了,主要难点就在于对next数组的求法和理解,KMP算法不是本文的重点,如有兴趣深入了解,推荐一篇博文:https://blog.csdn.net/v_july_v/article/details/7041827

另外还有Sunday算法 是找到与模式字符串相同长度的源字符串 从右向左匹配,其中心思想为:

  • 如果该字符没有在模式串中出现,直接从该字符向右移动位数 = 模式串长度 + 1。(因为源字符串含有该字符的相同长度字符串不可能匹配)
  • 如果该字符在模式串中出现过,其移动位数 = 模式串中最右端的该字符到末尾的距离+1。

字符串haystackBBC ABC 与模式串needle ABCDABD 匹配,字符串haystack中的空格字符未在模式串needle 中出现,则可以直接跳过空格字符后面六个字符的匹配,因为包含空格字符的相同长度字符串都不可能匹配成功,所以可以跳过6个。

Python3:

​ 说明:上面两种方法在所有语言都可行,只是语法不同,所以在py3中不再复现,仅展示一些py3特有的语法投机取巧解题。

利用py3内建函数find()直接得结果。

class Solution:def strStr(self, haystack: str, needle: str) -> int:return haystack.find(needle)

find() 方法描述
find() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,如果指定范围内如果包含指定索引值,返回的是索引值在字符串中的起始位置。如果不包含索引值,返回-1。如果子字符串为空,返回0。语法
str.find(str, beg=0, end=len(string))参数

  • str -- 指定检索的字符串
  • beg -- 开始索引,默认为0。
  • end -- 结束索引,默认为字符串的长度。

利用py3字符出切片特性解决:

class Solution:def strStr(self, haystack: str, needle: str) -> int:for i in range(len(haystack)-len(needle)+1):if haystack[i:i+len(needle)]==needle:#截取切片return ireturn -1

注:算法导论第32章:字符串匹配有完整的一章相关讨论。

Java实现穷举_LeetCode 28:实现strStr() Implement strStr()相关推荐

  1. java 实现穷举算法

    参考:https://blog.csdn.net/changyuanchn/article/details/51417796 题目 /*** * [0-1背包问题]有一个背包,背包容量是M=150kg ...

  2. Java实现穷举_对数器实现(C++)

    主要参考左神的JAVA版的对数器实现,主要分为以下几个步骤: 产生随机数组或者字符串,本例产生随机数组 找一个绝对正确的方法,不管复杂度 对比自己实现的方法和绝对正确的方法的结果,若相同,则返回tru ...

  3. java中穷举法排序_java穷举法小案例

    最近几天伤病没有更新  今天好点 看了一下基础的算法  现在简单更新一下 --穷举法 一.甲 .乙.丙 三位球迷分别预测进入半决赛的四队A.B.C.D的名次如下: 甲:A 第一名 .B 第二名 乙:C ...

  4. 遍历矩阵每一行穷举_LeetCode:二维数组—旋转矩阵

    点击上方蓝字关注我们 题目描述:"给衣服N*N的矩阵表示图像,其中每个像素的大小为4字节,设计一个算法,图像旋转90度" 示例: matrix=[[1, 2, 3],[4, 5, ...

  5. leetCode 28. Implement strStr() 字符串

    28. Implement strStr() Implement strStr(). Returns the index of the first occurrence of needle in ha ...

  6. java获取数组穷举_被BAT疯抢的Java工程师,都是怎么拿到年薪50W的offer

    怎样学习才能从一名Java初级程序员成长为一名合格的架构师,或者说一名遭到BAT疯抢的架构师. 那么遭到BAT疯抢的架构师应该有怎样的技术知识体系,这不仅是一个刚刚踏入职场的初级程序员也是工作三五年之 ...

  7. 关于Java穷举法对24点卡牌游戏规定时间内输入判断对错的程序

    24点游戏是经典的纸牌益智游戏. 常见游戏规则: 从扑克中每次取出4张牌.使用加减乘除,第一个能得出24者为赢.(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏. 随 ...

  8. 穷举法java_OpenJudge 4146:数字方格 java穷举法

    首先是题目描述: 描述 如上图,有3个方格,每个方格里面都有一个整数a1,a2,a3.已知0<=a1,a2,a3<=n,而且a1+a2是2的倍数,a2+a3是3的倍数,a1+a2+a3是5 ...

  9. java 穷举 排列组合,JavaScript递归穷举所有排列组合并找出重复值

    null export default { data() { return { resultArr:[] } }, mounted(){ this.sss('aaba','abac'); this.s ...

最新文章

  1. MongoDB 是什么 ? 能干嘛 ?
  2. mysql t添加注释_mysql—添加注释(comment)的用法
  3. HelloCnblogs
  4. advances search design time和runtime显示差异的原因
  5. 一条线一万美元的故事误导了你多少年
  6. POJ3485 区间问题
  7. 今天的不是陶渊明的 飞鸽传书
  8. 《Python程序设计基础》在亚马逊当当京东互动出版网淘宝等各大书店上架
  9. 虚拟云服务器 网站备案,云虚拟主机可以做备案吗
  10. 《一胜九败》读书笔记
  11. 规则引擎 drools_Drools的入门初探
  12. android之字体阴影效果
  13. bzoj2655 calc
  14. 如何查看或修改FANUC机器人的系统变量?
  15. Drools规则引擎实践直白总结,Java开发教程入门
  16. 微信公众号注册免费教程
  17. 大数据信息时代,如何防止数据泄露,大数据防泄漏解决方案
  18. python的自省与反射
  19. Python 函数库 APIs 编写指南
  20. BIOS设置 硬盘热插拔功能

热门文章

  1. 【二分图】洛谷P2055假期的宿舍
  2. [转载] epoll详解
  3. Java中的一些基础概念
  4. 建立SAP Router后,开放SAP访问的步骤
  5. 学习Altas 笔记[js调用重载的方法出错,如何处理]
  6. Python之文章生成器(升级版,也就是更傻瓜式运行)
  7. linux常用命令备忘(不断更新中...)
  8. wireshark: You don‘t have permission to capture on that device
  9. Libhybris之Glibc和Bionic共存时的TLS问题(四)
  10. WSL2安装GUI界面与音视频