LeetCode 刷題日記
EP.02

Set vs Dict
選對資料結構,解題事半功倍

#217 Contains Duplicate · #242 Valid Anagram

Joseph Chen
March 2026
Back to Blog
5 min read
1.2k views

刷 #217 Contains Duplicate 的時候,用 set 寫出來只需要兩行,但如果不懂 set,不管怎麼寫都很複雜。這一篇把 Python 的 set 和 dict 解釋清楚,並用兩道題展示它們各自最適合的場景。

先搞清楚:set 是什麼?

Python 有四種基本容器型別,常用的是 list 和 dict,但 set 才是做去重和存在性查詢的最佳選擇。

寫法型別可變?特性
[1, 2, 3]list有序、可重複、可用 index
(1, 2, 3)tuple有序、不可變
{1, 2, 3}set無序、不重複、O(1) 查詢
{"a": 1}dictkey-value 對應、O(1) 查詢
⚠️ 常見陷阱:{} 是空的 dict,不是 set!建立空 set 要用 set()
set 基本操作
# 建立 set
s = {1, 2, 3}
s = set([1, 2, 3, 3])   # 自動去重 → {1, 2, 3}
s = set()               # 空 set(不能用 {})

# 常用方法
s.add(4)                # 新增
s.remove(1)             # 刪除(不存在會報錯)
s.discard(99)           # 刪除(不存在不報錯)

# 最重要的操作:存在性查詢,O(1)
3 in s                  # True
99 in s                 # False

#217 Contains Duplicate:set 的主場

題目:給一個整數陣列,判斷是否有重複元素。

Input / Output
Input:  nums = [1, 2, 3, 1]
Output: True   ← 1 出現兩次

Input:  nums = [1, 2, 3, 4]
Output: False  ← 全都不重複

暴力解:兩層迴圈,每個元素跟所有其他元素比較,O(n²)。但用 set 可以一行解決:

set 解法 — O(n)
class Solution:
    def containsDuplicate(self, nums: list[int]) -> bool:
        return len(set(nums)) != len(nums)
        # set 自動去重,如果長度變短代表有重複
⏱ Time: O(n)💾 Space: O(n)

或者更明確的寫法,邊走邊查:

邊走邊查 — 找到重複就提早回傳
class Solution:
    def containsDuplicate(self, nums: list[int]) -> bool:
        seen = set()
        for num in nums:
            if num in seen:     # O(1) 查詢
                return True
            seen.add(num)
        return False

set 的查詢是 O(1),因為底層是 hash table。list 的查詢是 O(n),因為要一個一個比。同樣是「有沒有」的問題,選 set 差了整整一個數量級。

什麼時候用 set,什麼時候用 dict?

這是很多人模糊的地方:

用 set 當你只需要:

  • 某個值「有沒有出現過」
  • 去除重複元素
  • 集合運算(交集、聯集)

用 dict 當你需要:

  • 記錄某個值的「額外資訊」(index、次數)
  • key → value 對應關係
  • Two Sum 那種「查補數」

#242 Valid Anagram:dict 的主場

題目:給兩個字串,判斷是不是 anagram(字母異位詞)。Anagram 就是兩個字用一樣的字母,只是排列不同,例如 "anagram""nagaram"

Input / Output
Input:  s = "anagram", t = "nagaram"
Output: True

Input:  s = "rat", t = "car"
Output: False

為什麼不用 set?因為光知道「有沒有這個字母」不夠,還需要知道「各字母出現幾次」。這就是 dict 的用武之地。

dict 計頻率
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False

        count = {}

        for char in s:
            count[char] = count.get(char, 0) + 1   # 計 s 的字母頻率

        for char in t:
            count[char] = count.get(char, 0) - 1   # t 的字母扣掉

        return all(v == 0 for v in count.values())  # 全部歸零才是 anagram
⏱ Time: O(n)💾 Space: O(1) — 最多 26 個字母

Python 有個更簡潔的寫法,用 Counter

Counter 寫法(更 Pythonic)
from collections import Counter

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return Counter(s) == Counter(t)
        # Counter("anagram") → {'a': 3, 'n': 1, 'g': 1, 'r': 1, 'm': 1}
Counterdict 的子類別,專門用來計頻率。兩個 Counter 直接用 == 比較,內部會逐 key 比對 value,非常方便。

本篇重點整理

🔵set:只存值,不重複,O(1) 查詢 — 去重、判斷存在
🟡dict:key-value 對,O(1) 查詢 — 計頻率、記額外資訊
⚠️{} 是空 dict,空 set 要用 set()
💡Counter 是 dict 子類,計頻率首選
LeetCode
Array
Set
Dict
Counter
EP.02