Codetree 강의 화면(스크린샷 PDF)을 바탕으로 정리했습니다. fileciteturn0file0
1. 문제 요약
- 선택지 K개가 있고, 이를 N번 선택해 길이
N의 수열을 만든다. - 매번 선택은 독립적이라 같은 값을 여러 번 선택할 수 있다(중복 허용).
- 목표: 가능한 모든 수열을 사전식(또는 지정된 순서) 으로 출력(또는 탐색)한다.
예) K=2, N=3이면 가능한 수열 수는 2^3 = 8개
(1,1,1) ... (2,2,2) 처럼.
2. 핵심 개념: 중복순열(= K진수처럼 생각)
길이가 N인 수열의 각 자리에 K가지 선택지가 있으므로 전체 경우의 수는
즉, 완전탐색(Brute Force)로 전부 만들어도 입력 범위가 작으면 충분히 가능하다.
3. 재귀/백트래킹 설계
상태 정의
answer: 현재까지 만든 수열(리스트)curr_num: 몇 번째 자리를 채우고 있는지 (1부터 시작한다고 가정)
재귀 함수 의미
choose(curr_num)
→ curr_num번째 값을 정하고, 다음 자리로 넘어간다.
종료 조건(Base case)
curr_num == N + 1
→ 1~N번째까지 전부 채운 상태이므로answer를 출력하고 종료
점화(재귀 전개)
curr_num번째 자리에는1..K중 하나를 넣을 수 있다.- 하나 넣고 → 다음 자리로 재귀 → 되돌리기(pop)
4. 동작 예시 (K=2, N=3)
루트에서 첫 번째 자리를 고르고, 그 다음 두 번째, 세 번째 자리를 고르는 트리 구조가 된다.
depth 1 depth 2 depth 3
( ) ( ) ( )
/ \ / \ / \
1 2 1 2 1 2
결과 출력(한 줄에 하나씩):
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
5. Python 구현 예시
import sys
k, n = map(int, sys.stdin.readline().split())
answer = []
def choose(curr_num: int):
# base case: 1..n 까지 모두 채움
if curr_num == n + 1:
sys.stdout.write(" ".join(map(str, answer)) + "\n")
return
# curr_num 자리에 1..k 중 하나 선택
for x in range(1, k + 1):
answer.append(x)
choose(curr_num + 1)
answer.pop()
choose(1)
6. 시간 / 공간 복잡도
- 생성되는 수열 수:
K^N - 각 수열을 출력하려면 길이
N만큼 처리(출력 문자열 생성 등)가 들어가므로
- 재귀 깊이:
N,answer크기도 최대N
7. 자주 하는 실수 체크리스트
- 종료 조건 오프바이원
curr_num == n에서 출력해버리면 마지막 자리를 못 채우고 출력할 수 있음- 보통
curr_num == n + 1이 깔끔함(1-index 기준)
- pop() 누락
- 백트래킹에서 되돌리기 없으면
answer가 계속 쌓여서 틀림
- 백트래킹에서 되돌리기 없으면
- 출력 형식
- 문제에서 요구하는 공백/줄바꿈 형식 꼭 맞추기
- 속도
- 출력이 많으면
print()대신sys.stdout.write()가 유리할 때가 있음
- 출력이 많으면
8. 확장 아이디어
이 패턴은 “자리를 하나씩 채운다”는 구조라서 아래 문제들로 그대로 확장된다.
- 중복 허용 X → 방문 체크(
visited) 추가해서 순열 만들기 - 조합(순서 무시) → 다음에 선택 가능한 시작값(start) 관리
- 조건 만족 수열만 출력 → 중간에 조건 위배 시 가지치기(pruning)
이전링크드 리스트