문제 보기 · Level 1 · 고득점 Kit · 해시 · 정답률 60% · 푼 사람 119,670명 (2026-09-30 기준)1
문제
마라톤 참가자 명단과 완주자 명단이 주어진다. 완주하지 못한 사람은 정확히 한 명이다. 그 사람의 이름을 돌려준다.
- 참가자 1~100,000명
- 완주자 명단은 참가자보다 1명 적다
- 동명이인이 있을 수 있다
풀이
막히면 한 단계씩 펼친다.
필요한 개념
딕셔너리와 집합: 이름별로 몇 명인지 세는 표. Counter를 쓰면 더 짧다.
1단계 · 작은 예로 손으로 풀기
참가자 [“kim”, “lee”, “kim”], 완주자 [“lee”, “kim”]
- 참가자를 이름별로 센다: kim 2명, lee 1명
- 완주자만큼 뺀다: kim 2 − 1 = 1, lee 1 − 1 = 0
- 1명이 남은 이름 → “kim”
“kim”이 두 명이라 “명단에 있나 없나”만 보면 안 된다. 몇 명인지 세야 한다.
2단계 · 가장 단순한 방법과 그 속도
참가자마다 완주자 명단에서 찾아 지운다. 찾기와 지우기가 리스트에서는 명단을 훑는 일이라, 10만 × 10만 = 100억 번이다. 시간 안에 끝나지 않는다. 자세한 셈은 시간 복잡도로 방법 고르기의 예시에 있다.
3단계 · 핵심 아이디어
이름을 키로, 인원을 값으로 하는 딕셔너리를 만든다. 딕셔너리는 이름으로 칸을 바로 찾으니 한 사람을 처리하는 데 평균 한 번이면 된다.
- 참가자를 돌며 이름별 인원을 1씩 늘린다.
- 완주자를 돌며 1씩 줄인다.
- 0보다 큰 이름이 답이다.
떠올리는 신호: “두 명단을 비교”, “동명이인” → 이름별 개수를 센다.
4단계 · 코드 흐름
- 빈 딕셔너리
count를 만든다. - 참가자 이름마다
count[이름] += 1(처음이면 0에서 시작). - 완주자 이름마다
count[이름] -= 1. count를 돌며 값이 0보다 큰 이름을 돌려준다.
5단계 · 파이썬 코드
def solution(participant, completion):
count = {}
for name in participant:
count[name] = count.get(name, 0) + 1 # 없으면 0에서 시작
for name in completion:
count[name] -= 1 # 완주자는 반드시 참가자이므로 키가 있다
for name, c in count.items(): # (이름, 인원) 쌍을 차례로 꺼낸다
if c > 0:
return name
count.get(name, 0): name이 표에 없으면 0을 돌려준다.count.items(): 딕셔너리의 (키, 값) 쌍을 차례로 꺼낸다.
Counter를 쓰면 세기와 빼기가 한 줄이다.
from collections import Counter
def solution(participant, completion):
left = Counter(participant) - Counter(completion) # 빼고 0 이하인 이름은 사라진다
return list(left)[0] # 남은 이름은 하나뿐
6단계 · 실행 추적
참가자 [“kim”, “lee”, “kim”], 완주자 [“lee”, “kim”]
| 단계 | 한 일 | count |
|---|---|---|
| 참가자 kim | 0 + 1 | {kim: 1} |
| 참가자 lee | 0 + 1 | {kim: 1, lee: 1} |
| 참가자 kim | 1 + 1 | {kim: 2, lee: 1} |
| 완주자 lee | 1 − 1 | {kim: 2, lee: 0} |
| 완주자 kim | 2 − 1 | {kim: 1, lee: 0} |
값이 0보다 큰 kim을 돌려준다.
7단계 · 복잡도와 흔한 실수
명단을 두 번 훑으니 평균 \(O(n)\)이다.
set(participant) - set(completion)처럼 집합의 차를 쓰면 동명이인에서 틀린다. 집합은 같은 이름을 하나로 합쳐서, 위 예에서는 빈 집합이 된다.- 두 명단을 정렬해 앞에서부터 나란히 비교하는 방법도 맞다. 처음으로 달라지는 자리의 참가자가 답이고, 끝까지 같으면 참가자 명단의 마지막 사람이 답이다. 비용은 정렬 때문에 \(O(n \log n)\)이다.
Counter 풀이, 정렬 풀이가 모두 같은 답을 냈다 — 04_pg42576_p1.py-
프로그래머스 스쿨, “완주하지 못한 선수” (https://school.programmers.co.kr/learn/courses/30/lessons/42576), 2026-09-30 조회. ↩