백준 막 입문했을 때 재귀함수가 뭔지도 모르고 N-Queen 문제를 풀려고 했다가 3시간 넘게 삽질했던 기억이 난다. 다행히 이번 기회에 완전히 이해한 것 같다. 아마도...?

def gcd(x, y):
if y == 0:
return x
else:
return gcd(y, x % y)
print(gcd(22, 8)) # 2
gcd(22, 8) 실행 -> gcd(8, 6) 재귀호출gcd(8, 6) 실행 -> gcd(6, 2) 재귀호출gcd(6, 2) 실행 -> gcd(2, 0) 재귀호출gcd(2, 0) 실행 -> 2 반환2를 반환def recur(n):
if n > 0:
recur(n - 1)
print(n, end=" ")
recur(n - 2)
recur(4) # 1 2 3 1 4 1 2
n <= 0recur(4)부터 분석
recur(1)부터 분석
recur()에선 n을 출력하기 전 recur(n - 1)을 실행해야 함recur(n-1)의 처리가 마무리될 때까지 n을 어딘가에 저장해야 함 -> 스택!def recur(n):
stack = []
while True:
if n > 0:
stack.append(n)
n -= 1
continue
elif len(stack) != 0:
n = stack.pop()
print(n, end = " ")
n -= 2
continue
break
recur(4) # 1 2 3 1 4 1 2
n을 스택에 쌓고 n -= 1로 값을 변경recur(n-1) 호출과 같음n <= 0일 때 스택에서 값을 꺼내 n에 저장 및 출력하고, n -= 2로 값을 변경print(n) 후 recur(n-2) 호출과 같음
| 장점 | 단점 | |
|---|---|---|
| 재귀 | 문제를 보다 직관적이고 간결한 코드로 표현 가능 특히 하노이의 탑 등 분할정복 문제에 적합 | 너무 많은 재귀 호출 -> 스택 오버플로우 발생 가능 |
| 반복문 | 일반적으로 성능이 더 빠르며, 메모리 사용량이 더 적음 | 문제 코드가 덜 직관적 |



count = 0
# 원판 num개를 x기둥 -> y기둥으로 이동
def move(num, x, y):
global count
if num > 1:
move(num - 1, x, 6 - x - y)
count += 1
print(f"#{count:0>2}: 원반 {num}를 기둥 {x}->{y}로 이동")
if num > 1:
move(num - 1, 6 - x - y, y)
# 첫 기둥에 쌓인 원판 4개를 세번째 기둥으로 옮김
move(4, 1, 3)
#01: 원반 1를 기둥 1->2로 이동
#02: 원반 2를 기둥 1->3로 이동
#03: 원반 1를 기둥 2->3로 이동
#04: 원반 3를 기둥 1->2로 이동
#05: 원반 1를 기둥 3->1로 이동
#06: 원반 2를 기둥 3->2로 이동
#07: 원반 1를 기둥 1->2로 이동
#08: 원반 4를 기둥 1->3로 이동
#09: 원반 1를 기둥 2->3로 이동
#10: 원반 2를 기둥 2->1로 이동
#11: 원반 1를 기둥 3->1로 이동
#12: 원반 3를 기둥 2->3로 이동
#13: 원반 1를 기둥 1->2로 이동
#14: 원반 2를 기둥 1->3로 이동
#15: 원반 1를 기둥 2->3로 이동
num == 1
def n_queen(n):
rows = [0] * n # 각 행에서 퀸의 위치
cols = [False] * n # 각 열의 퀸 배치 여부
diag_a = [False] * (2 * n - 1) # ↖↘ 대각선에서의 퀸 배치 여부
diag_b = [False] * (2 * n - 1) # ↙↗ 대각선에서의 퀸 배치 여부
def show():
for p in rows:
print(f"{p:2}", end=" ")
print()
def place(i): # i행에 퀸을 배치
if i >= n: # 모든 행에 다 채운 경우 출력
show()
else:
for j in range(n):
if (not cols[j] and not diag_a[i - j + n - 1] and not diag_b[i + j]):
# 동일 열 및 대각선에 퀸이 없는 경우, i행 j열에 배치
rows[i] = j
cols[j] = diag_a[i - j + n - 1] = diag_b[i + j] = True
place(i + 1) # 다음 행으로 이동
# 퀸을 j열에서 제거
cols[j] = diag_a[i - j + n - 1] = diag_b[i + j] = False
place(0)
n_queen(8)
i >= n
대각선 열을 체크하는 방법
i >= N으로 모든 행에 퀸을 배치했을 경우, 하나의 경우이므로 1을 반환count 변수에 place_row를 호출하며 얻은 반환값을 누적해서 더해 반환N = int(input())
cols = [False] * N # 열 정보
diag_a = [False] * (2 * N - 1) # / 대각선 정보
diag_b = [False] * (2 * N - 1) # \ 대각선 정보
def place_row(i):
if i >= N:
return 1
count = 0
for j in range(N):
if (not cols[j] and not diag_a[i + j] and not diag_b[i - j + N - 1]):
cols[j] = diag_a[i + j] = diag_b[i - j + N - 1] = True
count += place_row(i + 1)
cols[j] = diag_a[i + j] = diag_b[i - j + N - 1] = False
return count
print(place_row(0))
