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

LeetCode 3325: Count Substrings With K-Frequency Characters I

·1 分鐘· ·
LeetCode Medium Sliding-Window Hash-Table String
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

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

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

解題思路
#

「至少一個字元出現至少 k 次」是單調的,用「至少」型的計數:

  • 右端加入字元 c,如果 c 剛好湊滿 k 次,視窗合法。
  • 合法時一直縮左邊,直到某個字元的數量從 k 掉到 k - 1(那就是唯一達標的字元剛被移出去)。
  • count += left。

縮之前視窗是不合法的(沒有字元達到 k),加入 c 後只有 c 可能達標,所以合法 ⇔ cnt[c] >= k,縮到 cnt[c] < k 就好。

我的嘗試
#

版本問題
第一版 WA把 k 寫死成 2。例如 s = "b"、k = 1:答案是 1,回傳 0
第二版 RE改用 k,但移出時判斷「不合法了」的條件寫成數量 == 1,應該是 == k - 1。k = 1 時數量會掉到 0,永遠不會等於 1,left 一路跑出字串
第三、四版 WA加上 left < n、left <= right 擋住越界,但門檻還是錯的。例如 s = "cc"、k = 1:答案是 3,第三版回傳 4;s = "bbb"、k = 3:答案是 1,第四版回傳 2
AC門檻改成 == k - 1

正確解法
#

class Solution:
    def numberOfSubstrings(self, s: str, k: int) -> int:
        cnt = Counter()
        left = count = 0
        for c in s:
            cnt[c] += 1
            while cnt[c] >= k:                     # 只有剛加入的 c 可能達標
                cnt[s[left]] -= 1
                left += 1
            count += left
        return count

直接用 cnt[c] >= k 當條件,比維護「達標的字元數」再判斷 == k - 1 簡單,也不會寫錯門檻。

複雜度
#

時間 O(n),空間 O(1)。

要特別避免的錯誤
#

  • 把 k 寫死。
  • 「離開達標」的門檻是 k - 1,不是 1。

面試口說整理
#

這是「至少」型的計數。加入字元前視窗不合法,加入後只有這個字元可能達到 k 次,所以它達到 k 次時我就一直縮左邊,縮到它少於 k 次,這時左端在 0 到 left - 1 都合法,加上 left。時間 O(n)。

相關文章

LeetCode 1358: Number of Substrings Containing All Three Characters
·1 分鐘
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 1358 解題筆記:「至少各一個 a、b、c」的計數視窗:三種都有時一直縮左邊,count += left
LeetCode 395: Longest Substring with At Least K Repeating Characters
·2 分鐘
LeetCode Medium Sliding-Window Divide-and-Conquer Hash-Table String
LeetCode 395 解題筆記:「每個字元至少 k 次」不單調,不能直接滑動;分治法用出現不到 k 次的字元切開,或枚舉視窗裡有幾種字元,固定種類數後就能滑動
LeetCode 2516: Take K of Each Character From Left and Right
·1 分鐘
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 2516 解題筆記:從兩端拿等於中間留一段;留下的每種字元最多是總數 − k,找最長的這種中間視窗
LeetCode 1016: Binary String With Substrings Representing 1 To N
·2 分鐘
LeetCode Medium Sliding-Window String Bit-Manipulation Hash-Table
LeetCode 1016 解題筆記:s 最多 1000 個字元,長度固定時的子字串數量有限,n 太大一定是 False;從 n 往下檢查會很快失敗,或從每個起點往右最多延伸 30 位收集所有 <= n 的值
LeetCode 3694: Distinct Points Reachable After Substring Removal
·1 分鐘
LeetCode Medium Sliding-Window Prefix-Sum Hash-Table String
LeetCode 3694 解題筆記:終點 = 全部的位移 − 被刪掉那段的位移;用長度 k 的視窗維護那段的位移,把每個終點放進 set
LeetCode 187: Repeated DNA Sequences
·1 分鐘
LeetCode Medium Hash-Table String Bit-Manipulation Sliding-Window
LeetCode 187 解題筆記:把每個長度 10 的子字串丟進雜湊表計數,出現超過一次的就是答案