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

LeetCode 402: Remove K Digits

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

基本資料
#

難易度: medium 第一次嘗試:2022-11-17

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

解題思路
#

要讓結果最小,越前面的位數越重要(Stack 模板四)。從左往右維護遞增的 stack:目前的數字比頂端小、而且還能刪(k > 0),就把頂端刪掉,因為用比較小的數字取代前面的位數一定更好。掃完之後 k 還有剩,就從尾巴刪(剩下的是遞增的,尾巴最大)。最後去掉前導零,空的就回傳 "0"。

我的嘗試
#

  • 第一版用了一個「在前 k + 1 個數字裡找最小值」的猜測,不是正確的貪心:"22"、k = 1 回傳 "22"。
  • 改成「刪掉第一個比下一個大的數字」之後,邊界條件 i != len(num) - 1 不夠,刪完之後 i 會超出範圍(IndexError),也沒有去掉前導零。改成 i < len(num) - 1 加上 str(int(num)) 才 AC,但每刪一個字元都要重建字串,是 O(nk)。

正確解法
#

class Solution:
    def removeKdigits(self, num: str, k: int) -> str:
        st = []
        for d in num:
            while k and st and st[-1] > d:
                st.pop()
                k -= 1
            st.append(d)
        if k:
            st = st[:-k]
        return "".join(st).lstrip("0") or "0"

複雜度
#

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

要特別避免的錯誤
#

  • 掃完 k 還有剩要從尾巴刪,例如 "22"、k = 1。
  • 去掉前導零,空字串回傳 "0"。
  • 每次刪一個字元就重建字串是 O(n²)。

面試口說整理
#

要讓數字最小,越前面的位數越重要,所以我維護一個遞增的 stack,遇到比頂端小的數字、而且還能刪,就把頂端刪掉;掃完還有剩的刪除次數就從尾巴刪,最後去掉前導零。每個數字最多進出一次,時間 O(n)。

相關文章

LeetCode 227: Basic Calculator II
·1 分鐘
LeetCode Medium Math String Stack
LeetCode 227 解題筆記:先把數字讀完整,遇到運算子時處理上一個運算子:+ - 把數放進 stack(減號放負數),* / 直接跟頂端算
LeetCode 71: Simplify Path
·1 分鐘
LeetCode Medium String Stack
LeetCode 71 解題筆記:用 / 切開,空字串和 . 跳過,.. 就 pop(根目錄不能再往上),其他名稱 push,最後用 / 接起來
LeetCode 324: Wiggle Sort II
·1 分鐘
LeetCode Medium Array Divide-and-Conquer Greedy Sorting
LeetCode 324 解題筆記:排序後分成小的一半和大的一半,各自反轉後交錯放:小的放偶數位置、大的放奇數位置
LeetCode 334: Increasing Triplet Subsequence
·1 分鐘
LeetCode Medium Array Greedy Longest-Increasing-Subsequence
LeetCode 334 解題筆記:維護目前最小的 first 和「前面有比它小的數」中最小的 second,遇到比 second 大的就找到了
LeetCode 397: Integer Replacement
·1 分鐘
LeetCode Medium Dynamic-Programming Greedy Bit-Manipulation Memoization
LeetCode 397 解題筆記:偶數一定除以 2;奇數選 +1 或 -1,用記憶化遞迴;n 很大不能開 n 大小的陣列
LeetCode 435: Non-overlapping Intervals
·1 分鐘
LeetCode Medium Array Dynamic-Programming Greedy Sorting
LeetCode 435 解題筆記:最少刪幾個 = 總數減掉最多能保留幾個;按右端點排序,貪心保留結束最早的