재귀 함수
- 자기 자신을 호출하는 함수
- 재귀(recursion) : 원래의 자리로 되돌아가거나 되돌아옴
- 자기 자신을 끝없이 호출하면서 같은 코드가 계속해서 실행
- 반복적인 작업을 해야하는 문제를 좀 더 간결한 코드로 풀어낼 수 있음
재귀로 문제 해결하기
- 문제를 좀 더 작게 쪼갭니다.
- 위와 같은 방식으로, 문제가 더는 작아지지 않을 때까지, 가장 작은 단위로 문제를 쪼갭니다.
- 가장 작은 단위의 문제를 풂으로써 전체 문제를 해결합니다.
Q. 자연수로 이루어진 리스트(배열)를 입력받고, 리스트의 합을 리턴하는 함수 arrSum
을 작성하세요.
arrSum([1, 2, 3, 4, 5]) === 1 + arrSum([2, 3, 4, 5])
arrSum([2, 3, 4, 5]) === 2 + arrSum([3, 4, 5])
...
...
arrSum([3, 4, 5]) === 3 + arrSum([4, 5])
arrSum([4, 5]) === 4 + arrSum([5])
arrSum([5]) === 5 + arrSum([])
arrSum([]) === 0;
arrSum([5]) === 5 + arrSum([]) === 5 + 0 === 5;
arrSum([4, 5]) === 4 + arrSum([5]) === 4 + 5 === 9;
arrSum([3, 4, 5]) === 3 + arrSum([4, 5]) === 3 + 9 === 12;
arrSum([2, 3, 4, 5]) === 2 + arrSum([3, 4, 5]) === 2 + 12 === 14;
arrSum([1, 2, 3, 4, 5]) === 1 + arrSum([2, 3, 4, 5]) === 1 + 14 === 15;
function arrSum (arr) {
if (arr.length === 0) {
return 0
}
return arr.shift() + arrSum(arr)
}
재귀를 사용하기 적합한 상황
- 주어진 문제를 비슷한 구조의 더 작은 문제로 나눌 수 있는 경우
- 중첩된 반복문이 많거나 반복문의 중첩 횟수(number of loops)를 예측하기 어려운 경우
- 반복문으로 작성된 코드를 더욱 간결하고 이해하기 쉽게 작성하고 싶은 경우
재귀의 활용
- 재귀 함수의 입력값과 출력값 정의하기 : 가장 단순하게 정의
- 문제를 쪼개고 경우의 수를 나누기 → 이때 중요한 관점은 입력값이나 문제의 순서와 크기
- 단순한 문제 해결하기 : 재귀의 기초 → 재귀의 탈출 조건(재귀 호출이 멈추는 조건)을 구성
- 남아있는 복잡한 문제 해결하고, 코드 구현하기
function recursive(input1, input2, ...) {
if (문제를 더 이상 쪼갤 수 없을 경우) {
return 단순한 문제의 해답;
}
return 더 작은 문제로 새롭게 정의된 문제
}
function arrSum(arr) {
if (arr의 길이가 0인 경우) {
return 0;
}
return 요소1 + arrSum([요소2, ... , 요소n]);
}
Q. 자연수를 입력받고, 입력받은 수부터 1까지의 자연수를 모두 곱한 값을 리턴하는 재귀 함수 fac
을 작성하세요.
function fac(n) {
if (n === 1) {
return 1;
}
return n * fac(n-1);
}