Skip to main content
코딩테스트 합격자 되기
3주차 스터디
기본과정 - 재귀
유투브 강의와 같이 보세요
책 구경하기
책 구매하기 미리보기(무료,180페이지)
저자와 소통하기
기본적인 자료구조/알고리즘 코드
꼭 알아야 할 개념이 포함된 코드
(성능측정/자주실수하는 코드 등)
책에 있는 문제의 정답코드
재귀의 정의
재귀(recursion)란?
자신이 자신을 호출하는 방법,
프로그래밍에서는 재귀 호출(recursive call)이라고 많이함
func
재귀의 정의를 보면 해당 함수구조는 재귀가 맞
습니다.
그런데 프로그래밍적으로도 문제가 없을까요?
재귀함수의 정의
재귀 함수(recursion function)의 정의 1/2
func
func
func
… recursion depth
재귀 함수(recursion function)의 정의 2/2
재귀함수는, 재귀의 정의에 아래조건 추가 필요
- 프로그래밍의 재귀는 무한한 재귀를 가지지 않는다.
반드시 base case가 존재한다.
- 같은 문제를 좀 더 간단한 문제로 감소 시키는 방식으로 동작한다.
f f f f
base case
바로 풀 수 있는 문제
재귀 예시 - 팩토리얼
팩토리얼의 정의 1/6
N!은 N부터 숫자를 하나씩 줄여가며 1 까지 모두 곱한 수
1!
2!
3!
N!
1
2 1
3 2 1
*
* *
N (N-1) (N-2)
* * 1
…
=
=
=
=
팩토리얼의 정의 - 반복문 2/6
3 1
N answer
3
2
1*3
3-1
6
1
3*2
2-1
6
0 1-1 exit while
반환
N=3
N=2
N=1
N=3일때 실제 동작
팩토리얼의 정의 - 반복문을 재귀로 변경해보자 3/6
1. 더 간단히 더 작게(Simpler & Smaller)
2. base case는 어떻게 될 것인가?
1!
2!
3!
1
2 1
3 2 1
*
* *
=
=
=
3!을 구할때 2!가 그대로 활용됨
2!을 구할때 1!가 그대로 활용됨
팩토리얼의 정의 - 반복문을 재귀로 변경해보자 4/6
N으로 일반화 하면 아래와 같이도 나타낼 수 있다.
무한히 호출하지 않은 1!이라는 base case 존재
여전히 팩토리얼 문제이지만, 문제크기가 줄어들고 있음
팩토리얼의 정의 - 반복문을 재귀로 변경해보자 5/6
있다고 믿는다는게 말이 됩니까!
- 네, 이미 내부 구현은 여러분들이 설계 했습니다. 점화식을 넣으면 됩니다.
팩토리얼의 정의 - 반복문을 재귀로 변경해보자 6/6
실제 재귀함수의 호출과정을 그리면 아래와 같습니다.
base case
재귀 예시 - 하노이 탑
하노이탑 게임 정의 1/11
3개의 기둥이 있고, 첫 번째 기둥에 길이가 긴 막대부터 차례대로 쌓아있다.
아래 규칙에 따라 세번 째 기둥에 모든 막대를 옮겨야 한다.
- 길이가 긴 막대가 길이가 짧은 막대 위에 있을 수 없다.
- 한번에 하나의 기둥만 옮길 수 있다.
첫 번째 기둥 두 번째 기둥 세 번째 기둥
하노이탑 게임 - 막대가 1개인 경우 2/11
1 > 3
하노이탑 게임 - 막대가 2개인 경우 3/11
1 > 2 1 > 3
2 > 3
하노이탑 게임 - 막대가 3개인 경우(con’t d) 4/11
1 > 3 1 > 2
1 > 3 2 > 1
3 > 2
하노이탑 게임 - 막대가 3개인 경우 5/11
1 > 3
2 > 3
하노이 탑 - 재귀로 구현해보자 6/11
1. 더 간단히 더 작게(Simpler & Smaller)
2. base case는 어떻게 될 것인가?
하노이 탑 - 재귀로 구현해보자(con’t d) 7/11
1 > 3 1 > 2 3 > 2
막대가 3개일 때 구하는 과정을 하나씩 쪼개서 봅시다
결국 막대 2개를 옮기는 연산과 같다
=> 하노이 탑에서 막대 2개 문제의 해로 해결 가능
하노이 탑 - 재귀로 구현해보자(con’t d) 8/11
막대가 3개일 때 구하는 과정을 하나씩 쪼개서 봅시다
결국 막대 1개를 옮기는 연산과 같다
=> 하노이 탑 막대 1개 문제의 해로 해결 가능
1 > 3
하노이 탑 - 재귀로 구현해보자(con’t d) 9/11
막대가 3개일 때 구하는 과정을 하나씩 쪼개서 봅시다
결국 막대 2개를 옮기는 연산과 같다
=> 하노이 탑 막대 2개 문제의 해로 해결 가능
2 > 1 1 > 3
2 > 3
1. 첫 번째 기둥의 맨 밑의 막대를 제외하고, 위에 있는 2개의 막대를 두 번째 기둥에 옮깁니다.
2. 첫 번째 기둥의 맨 밑의 막대를 세 번째 기둥에 옮깁니다.
3. 두 번째 기둥에 있는 막대 2개를 세 번째 기둥에 옮깁니다.
1. 첫 번째 기둥의 맨 밑의 막대를 제외하고, 위에 있는 1개의 막대를 두 번째 기둥에 옮깁니다.
2. 첫 번째 기둥의 맨 밑의 막대를 세 번째 기둥에 옮깁니다.
3. 두 번째 기둥에 있는 막대 1개를 세 번째 기둥에 옮깁니다.
1. 첫 번째 기둥의 맨 밑의 막대를 제외하고, 위에 있는 1개의 막대를 두 번째 기둥에 옮깁니다.
2. 첫 번째 기둥의 맨 밑의 막대를 세 번째 기둥에 옮깁니다.
3. 두 번째 기둥에 있는 막대 1개를 세 번째 기둥에 옮깁니다.
막대가 3개인 문제
막대가 2개인 문제
막대가 2개인 문제
1 2 3
1 3 2
: 막대 1개인 문제(base case)
하노이 탑 - 문제가 축소되는 과정 10/11
하노이 탑 - 최종 구현 11/11
1. 더 간단히 더 작게(Simpler & Smaller)
=> (N-1)개의 막대를 옮기는 문제 + 막대 1개를 옮기는 문제로 축소
* (N-1)개의 막대를 1번째 기둥에서 2 번째 기둥으로 옮김
* 첫 번째 기둥 맨 아래 막대를 3번째 기둥으로 옮김
* 두 번째 기둥의 (N-1)개의 막대를 3 번째 기둥으로 옮김
2. base case는 어떻게 될 것인가?
=> 막대 1개를 옮기는 문제(그냥 옮기면 됨)
막대 번호 옮길 막대 개수
출력값
1->3
1->2
3->2
1->3
2->1
2->3
1->3
재귀사용시 주의할 점
재귀 사용시 주의할 점
1. 실제 코드 동작시 함수 호출이 얼마나 되는지 드러나지 않음
2. 런타임 에러 발생시 에러가 코드에 명확히 보이지 않음
재귀 사용시 주의할 점 - 피보나치 수열 정의
- 수열의 맨 처음은 0과 1로 시작 즉 수열의 첫번째 수는 0, 두번째 수는 1
- n번째 피보나치 수는 (n-1)번째 수 + (n-2)번째 수
0 1 1 2 3 5
+
+
+
+
재귀 사용시 주의할 점 - 피보나치 수열 구현
반복문 재귀
N번 반복함
재귀함수가 2배로 늘어남
재귀 사용시 주의할 점 - 실제 재귀호출 모습
한 개의 fibonacci함수는, 두 개의 fibonacci를 호출하는 구
조이므로 호출횟수가 지수적으로 증가함
fibonacci(N)은 대략 2^(N-1)번 함수를 호출 함
이 부분은 코드에 잘 드러나지 않음!!
fibonacci(4)
재귀 사용시 주의할 점
1. 실제 코드 동작시 함수 호출이 얼마나 되는지 드러나지 않음
=> 재귀를 구현할 때 호출 횟수가 많이 증가하는 경우, recursion depth를 초과하지 않는지 확인 필요
2. 런타임 에러 발생시 에러가 코드에 명확히 보이지 않음
=> 복잡한 재귀함수는 반복문으로 작성 고려
재귀는 잘 사용할 경우, 코드를 간결하게 해주고 가독성을 높여 주지만, 명확하게 recursion depth를 고민하고 사용
하지 않으면 런타임 에러가 발생할 수 있습니다.
처음 연습하는 분들은 꼭 ppt처럼 call trace를 그림으로 작성해보시고 구현해주세요