문제 보기 · Level 2 · 2018 KAKAO BLIND RECRUITMENT (1차) · 정답률 67% · 푼 사람 25,932명 (2026-09-30 기준)1
문제
도시 이름 배열을 순서대로 조회한다. 캐시 크기는 cacheSize이고, 교체 방식은 가장 오래 쓰지 않은 것부터 버리는 LRU다. 캐시에 있으면(hit) 1, 없으면(miss) 5가 걸린다. 총 실행 시간을 돌려준다. 도시 이름은 대소문자를 구분하지 않는다.
- 0 ≤ cacheSize ≤ 30
- 도시 최대 100,000개, 이름 최대 20자
풀이
막히면 한 단계씩 펼친다.
필요한 개념
큐와 덱의 “가장 오래 안 쓴 것 버리기(LRU)”: 캐시를 쓴 순서대로 줄 세운 덱으로 만든다.
1단계 · 작은 예로 손으로 풀기
캐시 크기 2, 도시 [a, b, a, c, b] (왼쪽이 가장 오래 안 쓴 것)
| 도시 | 캐시에 있나 | 시간 | 캐시 |
|---|---|---|---|
| a | 없음 | +5 | [a] |
| b | 없음 | +5 | [a, b] |
| a | 있음 | +1, a를 맨 뒤로 | [b, a] |
| c | 없음, 가득 참 | +5, 맨 앞 b를 버림 | [a, c] |
| b | 없음, 가득 참 | +5, 맨 앞 a를 버림 | [c, b] |
총 21이다. 세 번째에 a를 맨 뒤로 옮기지 않았다면 c가 올 때 a가 버려졌을 것이다.
2단계 · 가장 단순한 방법과 그 속도
도시마다 캐시(최대 30개)를 훑어 있는지 본다. 10만 × 30 = 300만 번이라 넉넉하다. 캐시가 작아서 덱의 in과 remove가 \(O(30)\)이어도 괜찮다.
3단계 · 핵심 아이디어
덱을 “쓴 순서”로 유지한다. 맨 앞이 가장 오래 안 쓴 것이다.
- hit: 덱에서 빼서 맨 뒤에 다시 넣는다. 방금 썼기 때문이다.
- miss: 가득 찼으면 맨 앞을 버리고, 새 도시를 맨 뒤에 넣는다.
두 가지를 더 챙긴다. 이름은 소문자로 바꿔 비교한다. 캐시 크기가 0이면 아무것도 넣지 않고 모두 miss다.
4단계 · 코드 흐름
- 빈 덱과 시간 0을 준비한다.
- 도시마다 소문자로 바꾼다.
- 덱에 있으면: 빼서 맨 뒤에 넣고 +1.
- 없으면: +5. 크기 0이면 넘어간다. 가득 찼으면 맨 앞을 빼고, 도시를 맨 뒤에 넣는다.
- 시간을 돌려준다.
5단계 · 파이썬 코드
from collections import deque
def solution(cacheSize, cities):
cache = deque()
time = 0
for city in cities:
city = city.lower()
if city in cache: # hit
cache.remove(city)
cache.append(city) # 방금 쓴 것으로
time += 1
else: # miss
time += 5
if cacheSize == 0:
continue
if len(cache) == cacheSize:
cache.popleft() # 가장 오래 안 쓴 것 버리기
cache.append(city)
return time
continue: 이번 도시의 남은 줄을 건너뛰고 다음 도시로 간다.cache.remove(city): 덱 안에서 그 값을 찾아 지운다.
deque(maxlen=cacheSize)를 쓰면 더 짧다. 가득 찬 덱에 append하면 맨 앞이 저절로 빠지고, maxlen=0이면 아무것도 들어가지 않는다.
def solution(cacheSize, cities):
cache = deque(maxlen=cacheSize)
time = 0
for city in map(str.lower, cities):
if city in cache:
cache.remove(city)
time += 1
else:
time += 5
cache.append(city)
return time
6단계 · 실행 추적
캐시 크기 3, 도시 [Jeju, Pangyo, Seoul, Jeju, Pangyo, Seoul, Jeju, Pangyo, Seoul]
- 처음 세 개는 miss: 5 × 3 = 15, 캐시 [jeju, pangyo, seoul]
- 나머지 여섯 개는 모두 캐시에 있다: hit 6번 = 6
총 21이다. hit마다 맨 뒤로 옮겨도 세 도시가 모두 캐시에 남는다.
7단계 · 복잡도와 흔한 실수
도시 N개마다 캐시 K칸을 훑으니 \(O(NK)\)다(K ≤ 30).
- 대소문자를 구분해서
NewYork과newyork을 다른 도시로 본다. - hit일 때 맨 뒤로 옮기지 않는다. 그러면 LRU가 아니라 “먼저 넣은 것부터 버리기(FIFO)”가 된다.
- 캐시 크기 0을 따로 처리하지 않아, 빈 덱에서
popleft를 하다 오류가 난다.
OrderedDict로 만든 LRU 풀이와 maxlen 풀이가 모두 같은 결과를 냈다 — 11_pg17680_p1.py-
프로그래머스 스쿨, “[1차] 캐시” (https://school.programmers.co.kr/learn/courses/30/lessons/17680), 2026-09-30 조회. ↩