↓快轉到主要內容
  1. LeetCode/

LeetCode 809: Expressive Words

·2 分鐘· ·
LeetCode Medium Two-Pointers String Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2026-01-31

  • 提交紀錄:Runtime Error → Wrong Answer ×2 → Accepted

解題思路
#

把字串看成一段一段「連續相同字元」的組合,例如 "heeellooo" 是 h1 e3 l2 o3。word 能擴張成 s,代表兩邊的段數相同,而且每一段:

  • 字元相同;
  • 長度相同,或 s 那段長度 >= 3 且 >= word 那段的長度(只能擴張成 3 個以上,不能縮短)。

用兩個指針分別走 s 和 word,每次各自吃掉一整段、比較長度。迴圈結束後兩邊都必須剛好走完,否則有一邊多出整段字元。

我的嘗試
#

這題的錯都出在「結束條件」:

版本問題
第一版 RE迴圈只看 left < n,word 先走完時還去讀 word[right]。例如 s = "aab"、word = "aa" 直接 IndexError
第二版 WA改成 left < n and right < m,但結束後直接回傳 True,沒檢查 s 有沒有剩。同一個例子 "aab" / ["aa"] 回傳 1,答案是 0
第三版 WA補上 left == n,但沒檢查 word 有沒有剩。例如 s = "abc"、word = "abcd" 回傳 1,答案是 0

最後改成 left == n and right == m 才 AC。

正確解法
#

class Solution:
    def expressiveWords(self, s: str, words: List[str]) -> int:
        def run_end(t: str, i: int) -> int:           # 從 i 開始這段相同字元的結尾(不含)
            j = i
            while j < len(t) and t[j] == t[i]:
                j += 1
            return j

        def stretchy(word: str) -> bool:
            i = j = 0
            while i < len(s) and j < len(word):
                if s[i] != word[j]:
                    return False
                ni, nj = run_end(s, i), run_end(word, j)
                len_s, len_w = ni - i, nj - j
                if len_s != len_w and (len_s < 3 or len_s < len_w):
                    return False
                i, j = ni, nj
            return i == len(s) and j == len(word)

        return sum(stretchy(w) for w in words)

複雜度
#

時間 O(len(s) · 字數 + 所有 word 的總長度),空間 O(1)。

要特別避免的錯誤
#

  • 只用一個字串的長度控制迴圈:另一個先走完就越界。
  • 結束時沒檢查兩邊都走完。
  • 長度條件寫反:s 那段可以比較長,但不能比 word 短。

面試口說整理
#

我把字串看成一段一段相同字元,兩個指針各自吃掉一整段,比較字元和長度:長度相同可以,不同的話 s 那段要至少 3 個而且不少於 word。迴圈結束後要確定兩個字串都剛好走完。每個 word 都是線性掃一次。

相關文章

LeetCode 1989: Maximum Number of People That Can Be Caught in Tag
·1 分鐘
LeetCode Medium Two-Pointers Greedy Array
LeetCode 1989 解題筆記:鬼從左到右,每個鬼抓範圍內最左邊、還沒被抓的人;用一個只往右走的指針指向下一個候選人
LeetCode 1471: The k Strongest Values in an Array
·1 分鐘
LeetCode Medium Two-Pointers Sorting Array
LeetCode 1471 解題筆記:排序後離中位數最遠的一定在兩端,對撞指針每次從兩端挑比較強的那個,挑 k 次
LeetCode 2563: Count the Number of Fair Pairs
·2 分鐘
LeetCode Medium Two-Pointers Sorting Binary-Search Array
LeetCode 2563 解題筆記:把「和落在 [lower, upper]」拆成「和 <= upper」減「和 <= lower - 1」,每個都用排序後的對撞指針 O(n) 數
LeetCode 1498: Number of Subsequences That Satisfy the Given Sum Condition
·2 分鐘
LeetCode Medium Two-Pointers Sorting Binary-Search Array
LeetCode 1498 解題筆記:子序列只看最小值和最大值,排序後順序無關;固定最小值 nums[left],中間的元素任意選,共 2^(right - left) 種
LeetCode 1616: Split Two Strings to Make Palindrome
·2 分鐘
LeetCode Medium Two-Pointers String Greedy
LeetCode 1616 解題筆記:外側用 a 的前綴配 b 的後綴貪心比對,配不下去時,剩下的中間段必須整段在 a 或 b 裡是回文;兩個方向都要檢查
LeetCode 1750: Minimum Length of String After Deleting Similar Ends
·1 分鐘
LeetCode Medium Two-Pointers String
LeetCode 1750 解題筆記:兩端字元相同時,各自把同一段相同字元全部吃掉;整段都是同一個字元時可以刪光