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

LeetCode 2516: Take K of Each Character From Left and Right

·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-11

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

解題思路
#

跟 LeetCode 1423 一樣,從兩端拿 = 中間留下連續的一段。

拿到的每種字元至少 k 個 ⇔ 留下的每種字元最多 總數 − k 個。所以:

  1. 先算每種字元的上限 limit[c] = count[c] - k。有任何一個 < 0,代表總數就不夠,回傳 -1。
  2. 用「求最長」的滑動視窗找中間留下的最長一段:剛加入的字元超過上限就縮左邊。
  3. 答案是 n - 最長長度。

我的嘗試
#

這題的錯都在第一步的判斷:

版本問題
第一版 WA寫成 char not in freq or freq[char] < k。k = 0 時不需要任何字元,但字串裡沒有的字元還是被判成不夠。例如 s = "b"、k = 0:答案是 0,這版回傳 -1
第二、三版 RE改成 and(第三版再加 k > 0),變成字元存在但數量不夠時不會回傳 -1,上限變成負的,視窗怎麼縮都不合法,left 一路跑出字串。例如 s = "abc"、k = 2:直接 IndexError,答案是 -1
AC(k > 0 and char not in freq) or freq[char] < k

其實只要看 count[c] - k < 0 就夠了:Counter 對不存在的字元回傳 0,k = 0 時 0 - 0 不是負的。

正確解法
#

class Solution:
    def takeCharacters(self, s: str, k: int) -> int:
        limit = Counter(s)
        for c in "abc":
            limit[c] -= k                          # 中間最多能留幾個 c
            if limit[c] < 0:
                return -1

        cnt = Counter()
        left = best = 0
        for right, c in enumerate(s):
            cnt[c] += 1
            while cnt[c] > limit[c]:
                cnt[s[left]] -= 1
                left += 1
            best = max(best, right - left + 1)
        return len(s) - best

複雜度
#

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

要特別避免的錯誤
#

  • k = 0 時不需要任何字元。
  • 數量不夠時一定要提早回傳,否則上限是負的,視窗的迴圈會越界。

面試口說整理
#

從兩端拿,等於中間留下連續的一段,所以我把問題反過來:留下的每種字元最多是總數減 k,找最長的這種中間視窗,答案是總長減掉它。總數不夠就直接回傳 -1。用求最長的滑動視窗,剛加入的字元超過上限就縮左邊,時間 O(n)。

相關文章

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 的子字串丟進雜湊表計數,出現超過一次的就是答案
LeetCode 424: Longest Repeating Character Replacement
·1 分鐘
LeetCode Medium Hash-Table String Sliding-Window
LeetCode 424 解題筆記:可變長度滑動視窗,視窗長度減掉最多的字元次數就是要替換的數量,超過 k 就縮左邊
LeetCode 2831: Find the Longest Equal Subarray
·1 分鐘
LeetCode Medium Sliding-Window Hash-Table Binary-Search Array
LeetCode 2831 解題筆記:對每個值,把它出現的位置列出來;在位置列表上滑動視窗,要刪的數量 = 位置跨度 − 這個值的個數
LeetCode 1461: Check If a String Contains All Binary Codes of Size K
·1 分鐘
LeetCode Medium Hash-Table String Bit-Manipulation Rolling-Hash
LeetCode 1461 解題筆記:把所有長度 k 的子字串丟進集合,大小等於 2^k 就成立;最後一個起點是 len(s) - k