1. 程式人生 > 其它 >思路講解與演算法實現 LeetCode - 實現 strStr()

思路講解與演算法實現 LeetCode - 實現 strStr()

技術標籤:資料結構與演算法leetcode演算法java

聆聽 沉澱 傳播 … 關注微信公眾號【Java之言】,助你放棄程式設計之路!

每天一道演算法題,講解自己解題思路與實現;歡迎大家點評或者說出你的解題想法;也可評論想讓我講解哪道題!

文章目錄

題目

實現 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

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/implement-strstr/

一、思路

字串匹配,最簡單的,無非暴力匹配,但這效率是最低的。

如果不自己實現,現有很多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 - 陣列形式的整數加法

下一篇:敬請期待