Skip to content

Commit 616411a

Browse files
committed
docs: 05.md 내용 수정 및 재귀 알고리즘 예시 추가
1 parent 469bade commit 616411a

File tree

1 file changed

+81
-8
lines changed
  • docs/알고리즘-실무

1 file changed

+81
-8
lines changed

docs/알고리즘-실무/05.md

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: 재귀 알고리즘에 대해 이해하고 학습
66

77
## 1. 재귀 알고리즘의 기본 개념
88

9-
재귀(recursion)는 "함수가 정의될 때 자기 자신의 함수를 호출이 가능"하며, 이러한 자기 자신의 함수 호출을 **재귀 호출(recursive call)**이라고 합니다. 이는 **되부름 또는 순환**이라고도 표현됩니다. 재귀 알고리즘은 "어떤 사건이 자신을 다시 호출하여 작업을 수행하는 방식의 알고리즘"이며, 함수 형태로 많이 사용됩니다. 재귀를 효과적으로 사용하면 **프로그램을 간결하고 효율성 있게 작성**할 수 있습니다.
9+
재귀(recursion)는 "함수가 정의될 때 자기 자신의 함수를 호출이 가능"하며, 이러한 자기 자신의 함수 호출을 **재귀 호출(recursive call)** 이라고 합니다. 이는 **되부름 또는 순환** 이라고도 표현됩니다. 재귀 알고리즘은 "어떤 사건이 자신을 다시 호출하여 작업을 수행하는 방식의 알고리즘"이며, 함수 형태로 많이 사용됩니다. 재귀를 효과적으로 사용하면 **프로그램을 간결하고 효율성 있게 작성** 할 수 있습니다.
1010

1111
### 주요 특징
1212

@@ -31,13 +31,38 @@ description: 재귀 알고리즘에 대해 이해하고 학습
3131
### 재귀의 종류
3232

3333
- **직접 재귀:** "자신과 동일한 메서드를 호출하는 것"을 의미합니다.
34+
35+
```typescript
36+
// 직접 재귀 예시
37+
function directRecursion(n: number): number {
38+
if (n <= 0) return 0;
39+
return n + directRecursion(n - 1);
40+
}
41+
// directRecursion(3) → 3 + 2 + 1 + 0 = 6
42+
```
43+
3444
- **간접 재귀:** "메서드 a가 메서드 b를 호출하고, 다시 메서드 b가 메서드 a를 호출하는 구조로 이루어지는 것"을 의미합니다. 즉, "다른 메서드를 통해 자기 자신과 같은 메서드를 호출"합니다.
3545

46+
```typescript
47+
// 간접 재귀 예시
48+
function indirectA(n: number): number {
49+
if (n <= 0) return 0;
50+
return n + indirectB(n - 1);
51+
}
52+
function indirectB(n: number): number {
53+
if (n <= 0) return 0;
54+
return n + indirectA(n - 2);
55+
}
56+
// indirectA(3) → 3 + indirectB(2)
57+
// indirectB(2) → 2 + indirectA(0) → 2 + 0 = 2
58+
// indirectA(3) → 3 + 2 = 5
59+
```
60+
3661
---
3762

3863
## 2. 재귀 알고리즘의 적용 사례
3964

40-
### 2.1 팩토리얼(n!) 구하기
65+
### 팩토리얼(n!) 구하기
4166

4267
음이 아닌 정수 n의 팩토리얼은 재귀를 사용하여 구할 수 있는 대표적인 예시입니다.
4368

@@ -55,7 +80,7 @@ function factorial(n: number): number {
5580

5681
위 코드는 n이 0보다 클 때 n \* factorial(n-1)을 반환하여 재귀적으로 호출하고, n이 0이 되면 1을 반환하여 재귀를 종료합니다.
5782

58-
### 2.2 유클리드 호제법 (최대공약수 구하기)
83+
### 유클리드 호제법 (최대공약수 구하기)
5984

6085
두 정수의 최대공약수를 재귀적으로 구하는 방법입니다. 이는 직사각형을 정사각형으로 채우는 비유로 설명됩니다. 짧은 변의 길이를 한 변으로 하는 정사각형으로 채운 후 남은 직사각형에 같은 작업을 반복하며, 최종적으로 정사각형만으로 구성되었을 때 변의 길이가 최대 공약수가 됩니다.
6186

@@ -80,11 +105,11 @@ function gcd(x: number, y: number): number {
80105

81106
재귀 알고리즘을 분석하는 방법에는 크게 두 가지가 있습니다.
82107

83-
### 3.1 하향식 분석 (Top-down analysis)
108+
### 하향식 분석 (Top-down analysis)
84109

85110
"메서드를 호출하는 것부터 시작하여 계단식으로 자세히 조사해 나가는 분석 기법"입니다. 예를 들어 recur(4)를 호출할 때, 호출이 발생한 순서대로 스택에 쌓이는 과정을 추적합니다.
86111

87-
### 3.2 상향식 분석 (Bottom-up analysis)
112+
### 상향식 분석 (Bottom-up analysis)
88113

89114
"아래쪽부터 쌓아 올리며 분석하는 방법"입니다. 이는 재귀 호출의 가장 낮은 단계부터 시작하여 결과가 어떻게 반환되고 쌓이는지 역으로 추적하는 방식입니다.
90115

@@ -100,8 +125,56 @@ function gcd(x: number, y: number): number {
100125

101126
하노이의 탑 문제는 큰 원반을 먼저 옮기는 것이 아니라, 가장 큰 원반을 제외한 나머지 원반 그룹을 먼저 옮기는 방식으로 재귀적으로 해결됩니다.
102127

103-
1. 그룹을 시작 기둥에서 중간 기둥으로 옮깁니다. (가장 큰 원반을 제외한 n-1개의 원반)
104-
2. 바닥의 가장 큰 원반을 시작 기둥에서 목표 기둥으로 옮깁니다.
105-
3. 그룹을 중간 기둥에서 목표 기둥으로 옮깁니다. (중간 기둥으로 옮겨졌던 n-1개의 원반을 목표 기둥으로 최종 이동)
128+
```mermaid
129+
flowchart TD
130+
A[시작 기둥]
131+
B[중간 기둥]
132+
C[목표 기둥]
133+
134+
A -- "1단계: n-1개 원반 이동 (재귀)" --> B
135+
A -- "2단계: 가장 큰 원반 이동" --> C
136+
B -- "3단계: n-1개 원반 이동 (재귀)" --> C
137+
```
138+
139+
#### 하노이의 탑 3단계 이동 시각화
140+
141+
- **1단계:** n-1개 원반을 시작 기둥(A)에서 중간 기둥(B)로 이동 (재귀 호출)
142+
- **2단계:** 가장 큰 원반을 시작 기둥(A)에서 목표 기둥(C)로 이동
143+
- **3단계:** n-1개 원반을 중간 기둥(B)에서 목표 기둥(C)로 이동 (재귀 호출)
106144

107145
이러한 3단계 과정은 원반의 개수와 관계없이 동일하게 적용될 수 있습니다. move 메서드의 실행 과정을 통해 재귀 호출이 어떻게 단계적으로 진행되고 원반이 이동하는지 시각적으로 확인할 수 있습니다.
146+
147+
#### 하노이의 탑 TypeScript 예시 코드
148+
149+
```typescript
150+
function hanoiMoves(
151+
n: number,
152+
from: string,
153+
to: string,
154+
via: string
155+
): string[] {
156+
if (n === 1) {
157+
return [`${from} → ${to}`];
158+
}
159+
return [
160+
...hanoiMoves(n - 1, from, via, to),
161+
`${from} → ${to}`,
162+
...hanoiMoves(n - 1, via, to, from),
163+
];
164+
}
165+
166+
// 사용 예시: 3개의 원반을 A에서 C로 옮기기
167+
const moves = hanoiMoves(3, "A", "C", "B");
168+
console.log(moves);
169+
/*
170+
moves: [
171+
'A → B',
172+
'A → C',
173+
'B → C',
174+
'A → B',
175+
'C → A',
176+
'C → B',
177+
'A → B'
178+
]
179+
*/
180+
```

0 commit comments

Comments
 (0)