재귀 기본
- 주어진 문제를 비슷한 구조의 더 작은 문제로 나눌 수 있는 경우
- 중첩된 반복문이 많거나 반복문의 중첩 횟수(number of loops)를 예측하기 어려운 경우
1. 개념
function recursive(인자) {
if(조건 충족) {
return 결과
} else {
return recursive(작업된 인자)
}
}
- 재귀 : 문제를 해결할 때 동일한 구조의 더 작은 문제를 해결함으로써 주어진 문제를 해결하는 방법
*모든 재귀는 반복문으로 표현 가능
- 재귀 함수 : 스스로를 호출하는 함수
- 재귀 호출 : 재귀 함수는 실행 과정 중에 자기 자신을 호출하게 됨
*모든 재귀 함수는 함수의 호출 없이 while / for loop로 표현 가능
- 재귀를 사용한 코드 : 더욱 간결하고 이해하기 쉬움
2. 재귀적 사고
- 재귀 함수의 입력값과 출력값 정의하기 : 문제를 가장 추상적으로 단순하게 정의
- 문제를 쪼개고 경우의 수를 나누기 : 입력값이나 문제의 순서와 크기를 고려
- 단순한 문제 해결하기 : 문제를 더이상 쪼갤 수 없을 때까지 쪼개어 가장 해결하기 쉬운 문제부터 해결, 이를 base case라고 함
*base case : 재귀 함수 구현 시 재귀의 탈출 조건(재귀 호출이 멈추는 조건) 구성
- 복잡한 문제 해결하기 : 남아있는 문제 해결, 이를 recursive Case라고 함
*recursive Case : 자신을 호출하는 함수를 포함
- 코드 구현하기
function factorial(num) {
if(num === 1) {
return 1
}
return num * factorial(num - 1)
}
let myNumber = [1, 4, 5, 3, 2]
function arrSum(arr) {
if(arr.length === 0) {
return 0
}
return arr[0] + arrSum(arr.slice(1))
}
sum(0, myNumber)
3. 재귀 함수의 성능 문제
- 호출될 때마다 메모리에 스택이 쌓이는데, 한계치 이상으로 호출이 되어 스택이 넘쳐버리면 메모리 부족으로 에러 발생
- jump가 잦아 반복문에 비해 시간이 오래 걸림
- 꼬리 재귀 최적화 기능을 통해 해결 : return 값이 함수 자체 뿐
*꼬리 재귀 최적화 (Tail Call Optimization) : 재귀 함수를 컴퓨터가 재해석하여 선형 알고리즘을 만들어 실행, 아무리 반복이 일어나도 스택이 넘치지 않음
재귀 심화
1. 꼬리 재귀 (tail recursion in js)
2. 하노이의 탑 재귀 (js tower of hanoi in recursion)
3. 조합 재귀 함수 (js combination in recursion)
References
1. 재귀 함수