[LeetCode解題攻略] 28. Find the Index of the First Occurrence in

更新於 發佈於 閱讀時間約 7 分鐘

題目描述

實作一個函數 strStr(haystack, needle),用來找出字串 needle 在字串 haystack 中第一次出現的索引。如果 needle 不是 haystack 的一部分,則返回 -1


範例 1:

輸入

haystack = "sadbutsad", needle = "sad"

輸出

0

解釋needle 出現在 haystack 的索引 0 和 6 處。第一次出現在索引 0 處,所以回傳 0。

範例 2:

輸入

haystack = "leetcode", needle = "leeto"

輸出

-1

解釋needle 不在 haystack 中。


解題思路

要解決這個問題,我們需要從以下角度考慮:

  1. 字串匹配:找到 needle 是否存在於 haystack 中。
  2. 返回索引:如果匹配成功,返回第一個字符的索引;否則返回 -1

我們可以從最簡單的暴力匹配到更高效的演算法(如 KMP 演算法)進行討論。


解法一:暴力解法

思路

使用兩層迴圈:

  1. 外層迴圈遍歷 haystack 的每個字符作為起始位置。
  2. 內層迴圈檢查從該起始位置開始的子字串是否與 needle 匹配。

詳細步驟

  1. 檢查特殊情況:
    • 如果 needle 是空字串,返回 0。
    • 如果 needle 長度大於 haystack,直接返回 -1。
  2. 遍歷 haystack
    • 如果從當前索引開始的子字串與 needle 匹配,返回當前索引。
  3. 如果遍歷結束仍無匹配,返回 -1。

程式碼實現

class Solution:
def strStr(self, haystack: str, needle: str) -> int:
if not needle:
return 0
m, n = len(haystack), len(needle)
for i in range(m - n + 1):
if haystack[i:i + n] == needle:
return i
return -1

時間與空間複雜度

  • 時間複雜度:O((m−n+1)⋅n),其中 m 是 haystack 的長度,n 是 needle 的長度。
    • 外層迴圈最多執行 m−n+1 次。
    • 內層迴圈每次檢查 n 個字符。
  • 空間複雜度:O(1),未使用額外空間。

解法二:KMP 演算法(Knuth-Morris-Pratt Algorithm)

思路

暴力解法在每次失敗匹配時會回退至下一個起始位置,這會導致重複計算。KMP 演算法通過預處理 needle,構建一個「部分匹配表」(partial match table),在匹配失敗時快速跳過不必要的字符。


部分匹配表(LPS)的構建

LPS(Longest Prefix which is also Suffix)表記錄了 needle 的每個字符之前的最長前綴後綴匹配長度。

步驟

  1. 初始化一個長度為 n 的數組 lps,所有值為 0。
  2. 遍歷 needle,更新前綴後綴匹配長度。


詳細步驟

  1. 構建 LPS 表。
  2. 使用兩個指針進行匹配:
    • 一個指向 haystack(主串)。
    • 一個指向 needle(模式串)。

當匹配失敗時,根據 LPS 表跳過多餘的字符。


程式碼實現

class Solution:
def strStr(self, haystack: str, needle: str) -> int:
if not needle:
return 0

def buildLPS(pattern):
lps = [0] * len(pattern)
length = 0
i = 1
while i < len(pattern):
if pattern[i] == pattern[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]
else:
lps[i] = 0
i += 1
return lps

lps = buildLPS(needle)
i = j = 0

while i < len(haystack):
if haystack[i] == needle[j]:
i += 1
j += 1
if j == len(needle):
return i - j
elif i < len(haystack) and haystack[i] != needle[j]:
if j != 0:
j = lps[j - 1]
else:
i += 1
return -1

時間與空間複雜度

  • 時間複雜度:O(m+n),構建 LPS 表需要 O(n),匹配過程需要 O(m)。
  • 空間複雜度:O(n),需要額外的 LPS 表。

總結

  • 暴力解法簡單直接,但效率較低。
  • KMP 演算法適合處理長字串匹配問題,其預處理的部分匹配表能有效避免重複計算。

希望這篇教學能幫助大家更理解 LeetCode 第 28 題的解法!

歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
給定一個整數數組 nums 和一個值 val,需要就地刪除數組中所有等於 val 的元素,並返回刪除後數組的新長度。 要求在 O(1) 額外空間內完成操作,並且元素的相對順序不需要保持一致。
給定一個按非降序排序的整數數組 nums,就地刪除重複項,使得每個元素只出現一次。元素的相對順序應保持相同。然後傳回 nums 中唯一元素的數量。
給定一個鏈表,將鏈表的節點每 k 個一組進行反轉,並返回修改後的鏈表。如果節點總數不是 k 的倍數,則保留最後剩餘節點的順序。要求在不改變節點值的情況下進行反轉(即直接操作鏈表結構)。
給定一個鏈表,每次交換相鄰的兩個節點,返回交換後的鏈表。要求在不改變節點值的情況下進行節點交換(即直接操作鏈表結構)。
給定 k 個遞增排序的鏈表,將它們合併成一個遞增排序的鏈表,並返回合併後的鏈表。
給定一個整數 n,請生成所有可能由 n 對括號組成的 有效括號組合。
給定一個整數數組 nums 和一個值 val,需要就地刪除數組中所有等於 val 的元素,並返回刪除後數組的新長度。 要求在 O(1) 額外空間內完成操作,並且元素的相對順序不需要保持一致。
給定一個按非降序排序的整數數組 nums,就地刪除重複項,使得每個元素只出現一次。元素的相對順序應保持相同。然後傳回 nums 中唯一元素的數量。
給定一個鏈表,將鏈表的節點每 k 個一組進行反轉,並返回修改後的鏈表。如果節點總數不是 k 的倍數,則保留最後剩餘節點的順序。要求在不改變節點值的情況下進行反轉(即直接操作鏈表結構)。
給定一個鏈表,每次交換相鄰的兩個節點,返回交換後的鏈表。要求在不改變節點值的情況下進行節點交換(即直接操作鏈表結構)。
給定 k 個遞增排序的鏈表,將它們合併成一個遞增排序的鏈表,並返回合併後的鏈表。
給定一個整數 n,請生成所有可能由 n 對括號組成的 有效括號組合。
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
題目敘述 題目會給定我們兩個字串。 第一個是指定順序的字串order。 第二個是輸入字串s。 要求我們依據order給定的順序,重新排列s。 如果出現order中沒有出現的字母,任意位置皆可。 合法答案可能不只一組,輸出其中一種即可。 題目的原文敘述 測試範例 Example
Thumbnail
題目敘述 題目會給定一個鏈結串列 Linked List的頭部結點,要求我們根據索引的奇偶數重新排列。奇數索引的在前,偶數索引的在後。數的時候,從Head節點的索引=1開始數。 例如: 1 -> 2 -> 3 -> 4 -> 5 重新排列為 1 -> 3 -> 5 -> 2 -> 4
Thumbnail
題目敘述 題目會給我們一個字串s。 要求我們移除字串中的星號,還有刪除星號左手邊最靠近的第一個字元。 以字串的形式返回輸出答案。 題目的原文敘述 測試範例 Example 1: Input: s = "leet**cod*e" Output: "lecoe" Explanation:
Thumbnail
題目敘述 題目會給定兩個輸入。 第一個輸入是關鍵字清單products,第二個是使用者輸入的字串searchWord。 要求我們實現關鍵字搜尋建議系統,使用者每輸入一個字元就推薦一次。 推薦時,優先返回字典序(Lecial order)最接近的關鍵字,最多不要超過三個關鍵字。 題目的原文
Thumbnail
題目敘述 題目已經給定一個Trie前綴樹的類別和相關的函式介面interface, 要求我們把功能實作出來。 Trie() 建構子,初始化一個空的Trie。 void insert(String word) 插入一個新的單字word到Trie裡面。 boolean search(Strin
Thumbnail
題目敘述 題目會給我們一棵二元搜索樹的根結點root,還有一個指定的目標值val。 要求我們找出在樹中對應到目標值val的節點,假如找不到,請回傳null( null在Python就是None)。 題目的原文敘述 測試範例 Example 1: Input: root = [4,2,
Thumbnail
題目敘述 題目會給定一個整數陣列arr,要求我們判斷是否每個元素的出現次數都不同? 題目的原文敘述 測試範例 Example 1: Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurre
Thumbnail
題目 : 28. Find the Index of the First Occurrence in a String
Thumbnail
Find the Index of the First Occurrence in a String : 找出haystack在字串中第一次出現的index.
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
題目敘述 題目會給定我們兩個字串。 第一個是指定順序的字串order。 第二個是輸入字串s。 要求我們依據order給定的順序,重新排列s。 如果出現order中沒有出現的字母,任意位置皆可。 合法答案可能不只一組,輸出其中一種即可。 題目的原文敘述 測試範例 Example
Thumbnail
題目敘述 題目會給定一個鏈結串列 Linked List的頭部結點,要求我們根據索引的奇偶數重新排列。奇數索引的在前,偶數索引的在後。數的時候,從Head節點的索引=1開始數。 例如: 1 -> 2 -> 3 -> 4 -> 5 重新排列為 1 -> 3 -> 5 -> 2 -> 4
Thumbnail
題目敘述 題目會給我們一個字串s。 要求我們移除字串中的星號,還有刪除星號左手邊最靠近的第一個字元。 以字串的形式返回輸出答案。 題目的原文敘述 測試範例 Example 1: Input: s = "leet**cod*e" Output: "lecoe" Explanation:
Thumbnail
題目敘述 題目會給定兩個輸入。 第一個輸入是關鍵字清單products,第二個是使用者輸入的字串searchWord。 要求我們實現關鍵字搜尋建議系統,使用者每輸入一個字元就推薦一次。 推薦時,優先返回字典序(Lecial order)最接近的關鍵字,最多不要超過三個關鍵字。 題目的原文
Thumbnail
題目敘述 題目已經給定一個Trie前綴樹的類別和相關的函式介面interface, 要求我們把功能實作出來。 Trie() 建構子,初始化一個空的Trie。 void insert(String word) 插入一個新的單字word到Trie裡面。 boolean search(Strin
Thumbnail
題目敘述 題目會給我們一棵二元搜索樹的根結點root,還有一個指定的目標值val。 要求我們找出在樹中對應到目標值val的節點,假如找不到,請回傳null( null在Python就是None)。 題目的原文敘述 測試範例 Example 1: Input: root = [4,2,
Thumbnail
題目敘述 題目會給定一個整數陣列arr,要求我們判斷是否每個元素的出現次數都不同? 題目的原文敘述 測試範例 Example 1: Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurre
Thumbnail
題目 : 28. Find the Index of the First Occurrence in a String
Thumbnail
Find the Index of the First Occurrence in a String : 找出haystack在字串中第一次出現的index.