AlgorithmPython

LeetCode Python 踩坑紀錄

那些刷題時讓我卡關的 Python 細節,整理給自己也給你

Joseph Chen
April 30, 2026
Back to Blog
5 min read
1.2k views

用 Python 刷 LeetCode 本來應該是最輕鬆的選擇,語法簡潔、標準庫豐富。但有幾個細節讓我在某些題目上連錯好幾次,最後整理成這份紀錄,希望你不要踩同樣的坑。

這份筆記來自我的 GitHub repo chullin/leetcode,持續更新中。目前已完成 11 題,每題都嘗試用不同解法(Way1、Way2、Way3)來加深理解。

#1 pass by object reference(第 27 題)

這是我踩的第一個大坑。題目要求 in-place 修改陣列,我很直覺地寫:

bash
# ❌ 這樣寫無法修改原本的 list
nums = new_nums
Python 是 pass by object referencenums = new_nums 只是把區域變數 nums 的指向改掉,原本傳進來的那個 list 完全沒有被動到。

正確做法是用切片賦值,直接修改原本那塊記憶體的內容:

bash
# ✅ 切片賦值才能真正改掉原本的陣列
nums[:] = new_nums
記住:nums[:] 是在操作「這個 list 的內容」,而 nums = 是在操作「這個變數指向誰」。兩件完全不同的事。

#2 整數除法與四捨五入(第 3643 題)

Python 3 的除法行為和很多語言不同,/ 一律回傳 float,而 // 才是整數除法:

bash
9 / 2   # → 4.5  (float)
9 // 2  # → 4   (integer, floor division)

# 需要 ceil/floor 時要 import math
import math
math.ceil(9 / 2)   # → 5
math.floor(9 / 2)  # → 4

四捨五入更要小心,Python 內建的 round() 使用「銀行家捨入法」(四捨六入五取偶),不是你想像中的普通四捨五入:

bash
round(2.5)  # → 2  (不是 3!)
round(3.5)  # → 4
round(4.5)  # → 4  (不是 5!)
如果你的答案需要「標準四捨五入」,用 math.floor(x + 0.5)round() 更可靠。

#3 Python 的 Tuple Swap(第 3643 題)

這個是 Python 特有的語法糖,用來交換兩個變數超方便,在 Two Pointer 題型裡很常用:

bash
# 其他語言通常需要暫存變數
temp = list[a]
list[a] = list[b]
list[b] = temp

# Python 可以這樣寫
list[a], list[b] = list[b], list[a]
Python 會先把右邊打包成 tuple (list[b], list[a]),再同時 unpack 到左邊。這個「先求值右邊」的特性保證了交換的正確性,不需要暫存變數。

#4 Two Pointer 的思維(第 80、88 題)

做排序相關的題目時,in-place 操作幾乎都要用到 Two Pointer。關鍵是理解 slow / fast 兩個指針各自的職責:

bash
# slow:下一個有效值要放的位置
# fast:目前正在掃描的位置

# 第 88 題(Merge Sorted Array):從後往前填
# 因為 nums1 後面有空間,從後面開始才不會蓋掉還沒處理的資料
p1, p2, p = m - 1, n - 1, m + n - 1
while p1 >= 0 and p2 >= 0:
    if nums1[p1] > nums2[p2]:
        nums1[p] = nums1[p1]
        p1 -= 1
    else:
        nums1[p] = nums2[p2]
        p2 -= 1
    p -= 1

第 80 題(Remove Duplicates II)的技巧是:因為每個元素最多出現兩次,陣列前兩個元素一定合法,所以 slow 從 index 2 開始,直接比較 nums[fast]nums[slow - 2]

#5 dict.get(key, default) 防 KeyError

在用 HashMap 計數時,第一次出現的 key 如果直接 count[char] += 1, 會因為 key 不存在而拋出 KeyError。常見的解法有三種:

bash
# ❌ 直接操作不存在的 key → KeyError
count = {}
for char in s:
    count[char] += 1  # 第一次出現時 key 不存在,報錯!
bash
# ✅ 方法 1:dict.get(key, default)
count = {}
for char in s:
    count[char] = count.get(char, 0) + 1
# .get(char, 0) 的意思是:「取 count[char] 的值,如果不存在就回傳 0」

# ✅ 方法 2:defaultdict(int)
from collections import defaultdict
count = defaultdict(int)  # key 不存在時自動建立,預設值為 0
for char in s:
    count[char] += 1

# ✅ 方法 3:Counter(一行搞定)
from collections import Counter
count = Counter(s)  # 直接建好全部的計數
三種方法的語意相同,選擇看情境:
Counter 最簡潔,適合「一次性計算整個字串/陣列的頻率」。
defaultdict 適合「邊遍歷邊更新,還要做分組」(如 Group Anagrams)。
dict.get 不需要 import,適合在受限環境或想明確控制邏輯時使用。

#6 range(nums) 忘記 len()

在寫 Two Pointer 的 for 迴圈時,我犯過一個很低級的錯——把 list 本身傳給 range()

bash
# ❌ range() 需要整數,不能傳 list
for fast in range(1, nums):
    ...
# TypeError: 'list' object cannot be interpreted as an integer
bash
# ✅ 取 list 的長度再傳給 range()
for fast in range(1, len(nums)):
    ...
這種錯誤 Python 會立刻拋出 TypeError,所以不難找到。 但它說明了一個思維習慣問題:在 Python 裡 range(len(arr)) 幾乎是固定搭配, 把它當成一個整體記住。

#7 Counter 迭代順序 ≠ 頻率排序

做 #347 Top K Frequent Elements 時,我以為迭代 Counter 就能按頻率由高到低取得元素, 結果取到的是插入順序(Python 3.7+ dict 的預設行為),完全不是我要的結果。

bash
from collections import Counter

nums = [1, 1, 1, 2, 2, 3]
count = Counter(nums)

# Counter({'1': 3, '2': 2, '3': 1})  ← 印出來看起來是按頻率排
# 但這只是顯示格式,不代表迭代順序!

# ❌ 直接迭代取前 k 個
result = []
for num in count:     # 迭代順序是插入順序,不是頻率
    result.append(num)
    if len(result) == k:
        break
# 結果:取到的是最先出現的 k 個,不是頻率最高的 k 個!
bash
# ✅ 正確做法 1:most_common(k) 按頻率由高到低
[num for num, _ in count.most_common(k)]

# ✅ 正確做法 2:heapq.nlargest(O(n log k),更快)
import heapq
heapq.nlargest(k, count.keys(), key=lambda x: count[x])
Countermost_common() 才是按頻率排序的正確方法。 如果不傳參數,會回傳全部元素按頻率排序的 list;傳入 k 只回傳前 k 個,效率更高。

"刷題的目的不是背解法,而是把各種思維模式內化成直覺。"

目前進度

目前以 NeetCode 150 的順序為主,已完成:

#1Two Sum
#12Roman to Integer
#9Palindrome Number
#53Maximum Subarray
#27Remove Element
#217Contains Duplicate
#242Valid Anagram
#49Group Anagrams
#2Add Two Numbers
#26Remove Duplicates from Sorted Array
#169Majority Element
#229Majority Element II
#347Top K Frequent Elements

* 每個藍點代表一種解法,目標是每題都找到至少兩種解法。


PythonLeetCodeAlgorithmTwo PointerArray

看完有收穫嗎?

歡迎去 GitHub 看完整的題解紀錄,或繼續閱讀其他文章。