1 개요
Level 1~2 코딩 테스트는 알고리즘 아이디어보다 Python 내장 도구를 얼마나 잘 아는가가 체감 난이도를 결정한다. 아래 목록만 손에 익히면 Level 1은 거의 다 풀리고, Level 2도 논리 자체에 집중할 수 있다.
2 자료구조
2.1 list — 기본 배열 + 스택
# 생성
arr = [1, 2, 3] # arr = [1, 2, 3]
arr = [0] * 5 # arr = [0, 0, 0, 0, 0]
arr = list(range(5)) # arr = [0, 1, 2, 3, 4]
# 추가 / 삭제
arr = [1, 2, 3, 4]
arr.append(5) # arr → [1, 2, 3, 4, 5]
x = arr.pop() # x=5, arr → [1, 2, 3, 4]
x = arr.pop(0) # x=1, arr → [2, 3, 4] ← O(n)
arr.insert(1, 99) # arr → [2, 99, 3, 4]
arr.remove(99) # arr → [2, 3, 4]
# 조회
arr = [10, 20, 30, 40]
arr[0] # → 10
arr[-1] # → 40
arr[1:3] # → [20, 30]
# 기타
arr = [3, 1, 2, 1, 3]
arr.sort() # arr → [1, 1, 2, 3, 3]
arr.sort(reverse=True) # arr → [3, 3, 2, 1, 1]
arr.reverse() # arr → [1, 1, 2, 3, 3]
arr.count(3) # → 2
arr.index(2) # → 2 (인덱스 2에 위치)
len(arr) # → 5
# Level 1~2 자주 쓰는 패턴
arr = [1, -2, 3, -4]
result = [x * 2 for x in arr] # → [2, -4, 6, -8]
result = [x for x in arr if x > 0] # → [1, 3]2.2 set — 중복 제거 + O(1) 포함 여부 확인
# 생성
arr = [1, 2, 2, 3]
s = {1, 2, 3}
s = set([1, 2, 2, 3]) # s → {1, 2, 3} (중복 제거됨)
s = set() # s → set()
s = {1, 2, 3}
s.add(4) # s → {1, 2, 3, 4}
s.remove(2) # s → {1, 3, 4}
s.discard(99) # 오류 없음, s → {1, 3, 4}
3 in s # → True
len(s) # → 3
# 집합 연산
a = {1, 2, 3}
b = {2, 3, 4}
a | b # → {1, 2, 3, 4}
a & b # → {2, 3}
a - b # → {1}
a ^ b # → {1, 4}
# 패턴
arr = [1, 2, 2, 3, 3, 3]
unique_count = len(set(arr)) # → 32.3 dict — 카운팅 + 매핑
# 생성
d = {}
d = {'a': 1, 'b': 2}
d = dict(a=1, b=2)
# 핵심 연산
d = {'a': 1, 'b': 2}
d['a'] # → 1
d.get('c', 0) # → 0 (없는 키, 기본값 반환)
d['c'] = 3 # d → {'a': 1, 'b': 2, 'c': 3}
del d['a'] # d → {'b': 2, 'c': 3}
# 순회 (d = {'b': 2, 'c': 3} 기준)
for k in d: # k = 'b', 'c'
pass
for k, v in d.items(): # (k,v) = ('b',2), ('c',3)
pass
for v in d.values(): # v = 2, 3
pass
# 패턴: 카운팅
arr = ['a', 'b', 'a', 'c', 'b', 'a']
count = {}
for x in arr:
count[x] = count.get(x, 0) + 1
# count → {'a': 3, 'b': 2, 'c': 1}
# 또는 Counter 사용 (아래 참조)2.4 collections.Counter — 자동 카운팅
from collections import Counter
c = Counter([1, 2, 2, 3, 3, 3])
# c → Counter({3: 3, 2: 2, 1: 1})
c[3] # → 3
c[5] # → 0 (없는 키는 0 반환, KeyError 없음)
c.most_common(2) # → [(3, 3), (2, 2)]
list(c.keys()) # → [1, 2, 3] (순서는 빈도순)
list(c.values()) # → [3, 2, 1]
# 패턴: 가장 빈도 높은 원소
arr = [1, 2, 2, 3]
most_freq = Counter(arr).most_common(1)[0][0] # → 2
# 두 Counter 연산
a = Counter("hello") # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})
b = Counter("world") # Counter({'o': 1, 'w': 1, 'r': 1, 'l': 1, 'd': 1})
a - b # Counter({'h': 1, 'e': 1, 'l': 1}) (a에만 있는 것)
a + b # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, 'w': 1, 'r': 1, 'd': 1})2.5 collections.defaultdict — KeyError 없는 dict
from collections import defaultdict
d = defaultdict(int) # 기본값 0
d = defaultdict(list) # 기본값 []
d = defaultdict(set) # 기본값 set()
d = defaultdict(int)
d['x'] += 1 # d['x'] → 1 (초기화 없이 누적 가능)
d['x'] += 1 # d['x'] → 2
d['y'] # d['y'] → 0 (KeyError 없이 기본값 반환)
# 수동 카운팅
arr = ['a', 'b', 'a', 'c']
d = defaultdict(int)
for x in arr:
d[x] += 1
# d → defaultdict(int, {'a': 2, 'b': 1, 'c': 1})
# 그루핑
words = ['apple', 'banana', 'avocado', 'blueberry', 'cherry']
d = defaultdict(list)
for word in words:
d[word[0]].append(word)
# d → {'a': ['apple', 'avocado'], 'b': ['banana', 'blueberry'], 'c': ['cherry']}2.6 collections.deque — 빠른 큐
from collections import deque
q = deque([1, 2, 3])
q.append(4) # q → deque([1, 2, 3, 4])
q.appendleft(0) # q → deque([0, 1, 2, 3, 4])
q.pop() # → 4, q → deque([0, 1, 2, 3])
q.popleft() # → 0, q → deque([1, 2, 3])
# list.pop(0) 은 O(n), deque.popleft()는 O(1)
# BFS에서는 반드시 deque 사용
# BFS 패턴 예시
q = deque([5])
q.popleft() # → 5 (FIFO: 먼저 넣은 것 먼저 나옴)3 내장 함수
3.1 sorted() — 정렬 (원본 유지)
sorted([3, 1, 2]) # → [1, 2, 3] (원본 변경 없음)
sorted([3, 1, 2], reverse=True) # → [3, 2, 1]
# key 함수로 정렬 기준 지정 ← Level 2에서 핵심
arr = [(1,'b'), (3,'a'), (2,'c')]
sorted(arr, key=lambda x: x[1]) # → [(3,'a'), (1,'b'), (2,'c')]
words = ['banana', 'apple', 'fig', 'cherry']
sorted(words, key=len) # → ['fig', 'apple', 'banana', 'cherry']
sorted(words, key=lambda x: (-len(x), x))
# → ['banana', 'cherry', 'apple', 'fig'] (길이 내림차순, 같으면 사전순)
# 튜플 리스트 정렬
people = [("Kim", 30), ("Lee", 25), ("Park", 30)]
sorted(people, key=lambda x: (x[1], x[0]))
# → [("Lee", 25), ("Kim", 30), ("Park", 30)] (나이 오름차순, 같으면 이름)3.2 enumerate() — 인덱스 + 값 동시 순회
3.3 zip() — 두 리스트 병렬 순회
a = [1, 2, 3]
b = ['x', 'y', 'z']
list(zip(a, b)) # → [(1,'x'), (2,'y'), (3,'z')]
for x, y in zip(a, b):
print(x, y)
# → 1 x
# → 2 y
# → 3 z
# 패턴: 두 배열 동시 처리
result = [str(x) + y for x, y in zip(a, b)] # → ['1x', '2y', '3z']
# 언패킹 (전치)
matrix = [[1, 2], [3, 4], [5, 6]]
list(zip(*matrix)) # → [(1, 3, 5), (2, 4, 6)] (전치행렬)3.4 sum() / max() / min()
sum([1, 2, 3]) # → 6
sum([1, 2, 3], 10) # → 16 (초기값 10에서 시작)
max([1, 2, 3]) # → 3
min([1, 2, 3]) # → 1
# key 함수 적용
words = ['hi', 'hello', 'hey']
max(words, key=len) # → 'hello'
arr = [2, 7, 1, 9, 4]
min(arr, key=lambda x: abs(x - 5)) # → 4 (5에 가장 가까운 값)
# 2D 배열
matrix = [[1, 9], [3, 4]]
max(max(row) for row in matrix) # → 93.5 any() / all() — 조건 집계
3.6 range()
3.7 abs() / divmod() / pow()
abs(-5) # → 5
abs(3.14) # → 3.14
divmod(10, 3) # → (3, 1) — 몫=3, 나머지=1
divmod(17, 5) # → (3, 2) — 몫=3, 나머지=2
pow(2, 10) # → 1024
pow(2, 10, 1000) # → 24 (1024 % 1000) ← 모듈러 거듭제곱 (빠름)4 문자열 메서드
s = "Hello, World!"
# 변환
s.upper() # → "HELLO, WORLD!"
s.lower() # → "hello, world!"
s2 = " hello "
s2.strip() # → "hello"
s2.lstrip() # → "hello "
s2.rstrip() # → " hello"
s = "Hello, World!"
s.replace('l', 'L') # → "HeLLo, WorLd!"
# 분리 / 결합 ← 자주 씀
s.split(',') # → ['Hello', ' World!']
s.split() # → ['Hello,', 'World!']
'|'.join(['a','b','c']) # → 'a|b|c'
''.join(['a','b','c']) # → 'abc'
# 조회
s.count('l') # → 3
s.find('World') # → 7
s.find('xyz') # → -1 (없으면 -1)
s.startswith('He') # → True
s.endswith('!') # → True
'World' in s # → True
# 포맷
f"값: {3.14:.2f}" # → "값: 3.14" (f-string 권장)
# 패턴: 문자열 뒤집기
s = "hello"
s[::-1] # → "olleh"
# 패턴: 문자열 → 리스트 → 수정 → 문자열
chars = list("hello") # → ['h', 'e', 'l', 'l', 'o']
chars[0] = 'H' # → ['H', 'e', 'l', 'l', 'o']
''.join(chars) # → "Hello"5 수학 관련
import math
math.sqrt(16) # → 4.0
math.sqrt(2) # → 1.4142135623730951
math.ceil(3.2) # → 4 — 올림
math.floor(3.8) # → 3 — 내림
math.gcd(12, 8) # → 4 — 최대공약수
math.lcm(4, 6) # → 12 — 최소공배수 (Python 3.9+)
math.inf # → inf
math.factorial(5) # → 120
math.factorial(0) # → 1
# 정수 연산 (import 없이)
10 // 3 # → 3
10 % 3 # → 1
-10 % 3 # → 2 (Python은 항상 양수 나머지)
2 ** 10 # → 10246 itertools — Level 2에서 자주 등장
from itertools import combinations, permutations, product
# 조합 (순서 무관)
list(combinations([1,2,3], 2))
# → [(1,2), (1,3), (2,3)] — 3개 중 2개 선택, 순서 무관
# 순열 (순서 관련)
list(permutations([1,2,3], 2))
# → [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)] — 순서 있음
# 중복 조합
from itertools import combinations_with_replacement
list(combinations_with_replacement([1,2,3], 2))
# → [(1,1), (1,2), (1,3), (2,2), (2,3), (3,3)] — 중복 허용
list(product([1,2], ['a','b']))
# → [(1,'a'), (1,'b'), (2,'a'), (2,'b')] — 데카르트 곱
# 패턴: 모든 쌍의 합 구하기
arr = [1, 2, 3, 4]
sums = [a + b for a, b in combinations(arr, 2)]
# → [3, 4, 5, 5, 6, 7]7 유형별 사용 도구 매핑
| 문제 유형 | 핵심 도구 | 패턴 |
|---|---|---|
| 중복 제거/카운팅 | set, Counter |
len(set(arr)), Counter(arr).most_common() |
| 정렬 기준 커스텀 | sorted(key=) |
sorted(arr, key=lambda x: ...) |
| 인덱스 + 값 | enumerate |
for i, v in enumerate(arr) |
| 두 배열 병렬 | zip |
for a, b in zip(A, B) |
| 빈도 카운팅 | Counter, defaultdict(int) |
d[x] += 1 |
| 그루핑 | defaultdict(list) |
d[key].append(val) |
| BFS | deque |
q.popleft() |
| 조합/순열 | combinations, permutations |
완전탐색 Level 2 |
| 문자열 분리 | split, join |
s.split(), ''.join(arr) |
| 합/최대/최소 | sum, max, min |
max(arr, key=...) |
8 복잡도 요약
| 연산 | list | set | dict |
|---|---|---|---|
| 조회 | O(n) | O(1) | O(1) |
| 삽입 | O(1) 끝 / O(n) 중간 | O(1) | O(1) |
| 삭제 | O(n) | O(1) | O(1) |
| 포함 여부 | O(n) | O(1) | O(1) |
x in arr 이 느리다고 느껴지면 set 으로 바꾸는 것을 먼저 고려한다.
9 관련 문제
- 포켓몬 (Hash Level 1) —
set,len,min - 완주하지 못한 선수 (Hash Level 1) —
Counter,dict - 전화번호 목록 (Hash Level 2) —
startswith,set