[2164] 카드2

 

백준 Silver IV | 2164 | Python | 문제 링크

문제 설명

N장의 카드가 1부터 N까지 순서대로 쌓여 있다. 맨 위 카드를 버리고, 그 다음 맨 위 카드를 맨 아래로 옮기는 동작을 카드가 1장 남을 때까지 반복한다. 마지막에 남은 카드 번호를 출력하면 된다.

입력

첫째 줄에 N (1 ≤ N ≤ 500,000)이 주어진다.

출력

마지막에 남은 카드의 번호를 출력한다.

입출력 예

입력 출력
6 4
 

나의 풀이

풀이 1 - 무한루프가 걸린 첫 제출

from collections import deque
import sys
input = sys.stdin.readline

q = deque()
num = int(input())
for i in range(1, num+1):
    q.append(i)

while q:
    if len(q) == 1:
        print(q[0])       # break가 없다
    else:
        q.popleft()
        q.append(q.popleft())

문제 자체는 어렵지 않았다. deque로 카드 덱을 만들고, popleft()로 버리고, 다시 popleft()해서 append()로 맨 아래에 넣으면 된다. 논리는 맞았다.

제출하고 시간 초과가 떴다. 처음엔 알고리즘 복잡도 문제인가 싶었는데, 코드를 다시 보니 그게 아니었다.

버그 1 — break가 없다

if len(q) == 1:
    print(q[0])

len(q) == 1일 때 출력은 하는데 루프를 빠져나오지 않는다. while q:는 큐가 비어있어야 종료되는데, 카드 1장이 남아있는 채로 계속 돈다. print만 무한히 반복되는 것이다.

출력이 쌓이다 보니 시간 초과로 잡혔다. 무한루프인데 시간 초과로 나오니까 처음에는 영문을 몰랐다. break 한 줄이 빠진 것 때문에 이렇게 됐다는 게, 고치고 나서도 좀 허무했다.

풀이 2 - 최종 제출 코드

from collections import deque
import sys
input = sys.stdin.readline

q = deque()
num = int(input())
for i in range(1, num+1):
    q.append(i)

while q:
    if len(q) == 1:
        print(q[0])
        break           # break 추가
    else:
        q.popleft()
        q.append(q.popleft())

break를 붙이니 바로 통과했다. 코드는 맞는데 루프 종료 조건을 명시적으로 설계하지 않은 게 문제였다.

풀이 3 - 루프 조건 개선

from collections import deque
import sys
input = sys.stdin.readline

q = deque(range(1, int(input()) + 1))

while len(q) > 1:
    q.popleft()
    q.append(q.popleft())

print(q[0])

while len(q) > 1:로 조건을 바꾸면 카드가 1장 남는 순간 자연스럽게 루프가 끝난다. if/elsebreak가 둘 다 필요 없어진다. 초기화도 deque(range(1, n+1))로 한 줄로 줄었다.

while q:를 쓰면 큐가 빌 때까지 돌기 때문에 탈출 시점을 코드 안에서 따로 처리해야 한다. while len(q) > 1:은 종료 조건을 루프 헤더에서 바로 표현하기 때문에 break가 끼어들 여지가 없다.

break 한 줄이 빠져서 무한루프가 된 이번 실수도, 애초에 루프 조건을 이렇게 썼다면 일어나지 않았을 것이다.

'CodingTest > BeakJoon' 카테고리의 다른 글

[7785] 회사에 있는 사람  (0) 2026.03.24
[1920] 수 찾기  (0) 2026.03.24
[10845] 큐  (0) 2026.03.24
[10828] 스택  (0) 2026.03.24
[10773] 제로  (1) 2026.03.23