"해시맵을 만들 필요 없어 — Python 이 세계적인 거 둘을 건네. 능력은 그걸 구현하는 게 아니라; 그것들이 O(n²) 를 O(n) 으로 바꾸는 일상 문제 열두 개를 알아보는 거야."
연산이 다 O(1)
이 트랙의 모든 이론이 여기서 현금화돼. dict 에서: d[k] 읽기, d[k] = v 쓰기, k in d 멤버십, del d[k] — 다 평균 O(1). set 에서: add, remove, x in s — 다 평균 O(1). 집합 대수 (a | b 합집합, a & b 교집합, a - b 차집합) 는 곱이 아니라 집합 크기에 비례한 시간에 돌아. 이게 building block 이고; 예술은 맞는 순간에 손대는 거야.
외울 가치 있는 패턴
- 중복 제거:
set(items)— 고유 원소, 즉시. - 멤버십:
x in some_list대신x in some_set— O(n) 대 O(1), 가장 흔한 속도 향상. - 세기:
collections.Counter(items)— 한 패스에 각 원소 빈도. - 묶기:
collections.defaultdict(list)— '이 키가 이미 있나?' 확인 없이 키로 항목 버킷. - 캐싱 / 메모이제이션: 입력을 계산된 결과로 매핑하는
dict— Dynamic Programming 트랙의 심장. - two-sum 트릭: 한 패스, 본 걸 dict 에 기억, 보수가 이미 있는지 확인 — O(n²) 대신 O(n).
dict 와 set 은 평균 O(1) 조회, 삽입, 삭제, 멤버십을 줘. 능력은 패턴 인식이야: 중복 제거 → set, 세기 → Counter, 묶기 → defaultdict, '전에 봤나?' → set, '답을 기억' → dict. 그것들로 손대는 게 존재하는 가장 흔한 현실 최적화야.
영원히 값하는 반사신경
지을 습관: 반복문에 if x in a_list 가 있거나, 쌍/매칭을 찾으려 반복문을 중첩할 때마다, set 이나 dict 가 그걸 O(n²) 에서 O(n) 으로 바꾸는지 물어. 거의 늘 그렇고, 거의 늘 작은 변경이야. two-sum 문제가 완벽한 상징이야 — 무차별은 모든 쌍 확인 (O(n²)); dict 버전은 가면서 각 수를 기억하고 보수를 O(1) 에 확인해, 전체를 O(n) 으로 무너뜨려. 같은 답, 다른 구조, 범주적으로 더 빠른 프로그램.
피파의 고백
초반에, 내가 쓴 거의 모든 느린 함수가 같은 병이었어: 반복문 안
in list 확인. 아빠가 로직 리뷰를 멈추고 그냥 그 줄들에 동그라미 치기 시작했어: "set. set. 저건 dict." 고침은 각자 한 단어였고, 몇 초짜리 함수를 일상적으로 즉시로 바꿨어. 반사신경으로 체화했어 — 이젠 반복문 안에서 in 이 리스트를 만나면 작은 경보가 울려. 그 반사신경 하나가 내가 쓴 어떤 영리한 알고리즘보다 많은 런타임을 아꼈을 거야.