1.题目
https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/
leetcode 28
字符串匹配之BF(Brute Force)算法是一种简单的字符串匹配算法,也叫暴力匹配算法。它的思想是将目标串 S 的第一个字符与模式串 T 的第一个字符进行匹配,如果相等,就继续比较 S 的第二个字符和 T 的第二个字符,如果不相等,就比较 S 的第二个字符和 T 的第一个字符,依次比较下去,直到找到一个匹配或者遍历完整个目标串
这个算法的时间复杂度是 O(mn) ,其中 m 和 n 是目标串和模式串的长度。空间复杂度是 O(1) ,因为不需要额外的空间
BF算法的优点是
简单易懂,实现起来不复杂,适用于短字符串的匹配。
BF算法的缺点是
效率较低,每次匹配失败时都要回溯主串和模式串的指针,导致大量的重复比较,时间复杂度为 O(nm) ,其中 n 是主串的长度,m 是模式串的长度。
2.解法
解法一:双指针,一个字符一个字符比较
这个实现的思想是定义一个指针 i 指向目标串 S 的当前位置,定义一个指针 j 指向模式串 T 的当前位置。每次比较 S[i] 和 T[j] ,如果相等,就让 i 和 j 都加一,继续比较下一个字符。如果不相等,就让 i 回退到上一次匹配的下一个位置,让 j 重置为 0 ,重新开始匹配。如果 i 超过了 S 的长度,或者 j 等于了 T 的长度,就结束循环。如果 j 等于了 T 的长度,说明找到了一个匹配,返回 i - j 作为匹配的起始位置。如果 i 超过了 S 的长度,说明没有找到匹配,返回 -1 作为标志。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class StringBF { public static void main(String[] args) { String s = "leetcode" ; String t = "tco" ; System.out.println(bruteForce(s, t)); } public static int bruteForce(String s, String t) { int i = 0 , j = 0 ; while (i < s.length() && j < t.length()) { if (s.charAt(i) == t.charAt(j)) { i++; j++; } else { i = i - j + 1 ; j = 0 ; } } if (j == t.length() ) { return i - j; } return - 1 ; } } |
解法二:滑动窗口+ subString 整体比较
思路
BF算法在 JDK 中有一些应用,比如 String 类的 indexOf() 方法和 lastIndexOf() 方法,都是使用 BF 算法来实现的。这些方法可以用来查找一个字符串中是否包含另一个字符串,或者返回一个字符串在另一个字符串中的位置
BF算法,也就是暴力匹配算法。它的基本思想是,从haystack的第一个字符开始,依次与needle的每个字符进行比较,如果都相等,就返回当前的索引;如果有不相等的,就从haystack的下一个字符开始,重复这个过程,直到找到匹配的子字符串或者遍历完haystack为止。
代码逻辑
- 首先,检查haystack和needle是否为空,如果是,就返回-1,因为这是一个无效的输入。
- 其次,检查haystack和needle是否相等,如果是,就返回0,因为这意味着needle就是haystack的第一个子字符串。
- 然后,获取needle的长度,用它作为滑动窗口的大小。
- 接着,从左到右遍历haystack,每次取出一个长度为needleLength的子字符串,与needle进行比较。
- 如果相等,就返回当前的索引i,表示找到了needle在haystack中的第一个位置。
- 如果不相等,就继续向右滑动窗口,直到遍历完整个haystack或者找到匹配的子字符串为止。
- 最后,如果遍历完haystack都没有找到匹配的子字符串,就返回-1,表示needle不是haystack的一部分。
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class ImplementStrStr { public int strStr(String haystack, String needle) { // 基本条件 if (haystack == null || needle == null ) { return - 1 ; } // 特殊情况 if (haystack.equals(needle)) { return 0 ; } // needle的长度 int needleLength = needle.length(); // 遍历haystack并滑动窗口 for ( int i = 0 ; i < haystack.length() - needleLength + 1 ; i++) { // 检查子字符串是否等于needle if (haystack.substring(i, i + needleLength).equals(needle)) { return i; } } return - 1 ; } } |
3.总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2019-04-10 web.xml中<load-on-start>n</load-on-satrt>作用
2019-04-10 JavaWeb中filter的详解及应用案例
2019-04-10 Tomcat的简单归纳总结
2019-04-10 Tomcat 配置详解和优化
2019-04-10 深入理解Tomcat
2019-04-10 Tomcat启动过程原理详解
2019-04-10 Tomcat的目录结构详细介绍(超全)