재귀(Recursion) 함수
재귀(Recursion)
: 원래의 자리로 되돌아가거나 되돌아옴.
예시
#1
function arrSum(arr) {
// base case : 문제를 더 이상 쪼갤 수 없는 경우 (재귀의 기초)
if (arr.length === 0) {
return 0;
}
// recursive case : 그렇지 않은 경우
return arr[0] + arrSum(arr.slice(1));
}
arrSum([1,2,3,4,5]) //15arr[0]은 첫 번째 요소, arrSum(arr.slice(1))은 첫 번째 요소를 제외하고 자기 자신을 호출을 반복한다.
그 결과, 1 + [2,3,4,5], 2 + [3,4,5], 3 + [4,5], 4 + [5], 5 + [ ]가 되어 arr.length === 0에 속해 0을 반환하면 5 + 0 , 4 + 5, 3 + 9, 2 + 12, 1 + 14해서 최종적으로 15가 나온다.

이 그림을 보니까 더 잘 이해가 되는 것 같다.
#2
// factorial 문제
function factorial(n) {
if(n ===1){
return 1;
}
return n * factorial(n-1);
}
fac(4) // 24return 4 * fac(3), return 3 * fac(2), return 2 * fac(1)이 되고, fac(1)은 1이기 때문에 다시 그 결과를 거슬러 올라가면 2 * 1, 3 * 2, 4 * 6해서 최종적으로 24가 나오게 된다.
이것이 재귀 함수이다.
코플릿
오늘 재귀 코플릿을 풀면서 어려웠던 문제들이 많았다. 헷갈렸던 문제들을 다시풀어보고 풀이하도록 하겠다.
02_isOdd
function isOdd(n) {
// 만약 0이면 짝수
if(n === 0){
return false;
}
// 만약 1이면 홀수
if(n === 1){
return true;
}
// 먄약 n이 음수이면 양수로 변환
if(n < 0>){
return isOdd(-num)
}
return isOdd(n-2);
}
let output = isOdd(17);
console.log(output); // --> true
output = isOdd(-8);
console.log(output); // --> false08_drop
function drop(n, arr) {
if(n === 0 || arr.length === 0){
return arr;
}
return drop(n-1, arr.slice(1))
}
let output = drop(2, [1, -2, 1, 3]);
console.log(output); // --> [1, 3]
output = drop(5, [1, -2, 1, 3]);
console.log(output); // --> [ ]n이 작아지면서 arr는 첫 번째 요소를 제외하고 자기 자신을 호출한다.
09_take
function take(n, arr) {
// n이나 배열이 0인 경우 빈 배열을 리턴한다.
if(n === 0 || arr.length === 0){
return [ ];
}
return [arr[0]].concat(take(num-1, arr.slice(1)));
}
let output = take(2, [1, -2, 1, 3]);
console.log(output); // --> [1, -2]
output = take(5, [1, -2, 1, 3]);
console.log(output); // --> [1, -2, 1, 3][1].concat(take(1, [-2, 1, 3])), [-2].concat(take(0, [1, 3]))해서 n이 0이기 때문에 빈 배열을 리턴한다.
다시 정리하면, [-2].concat([ ]) = [-2], [1].concat([-2]) = [1, -2]해서 최종적으로 [1, -2]가 나온다.
12_reverseArr
function reverseArr(arr) {
// 배열이 0인 경우 빈 배열을 리턴한다.
if(arr.length === 0){
return [];
}
//
return [arr[arr.length -1]].concat(reverseArr(arr.slice(0, arr.length -1)));
}
let output = reverseArr([1, 2, 3]);
console.log(output); // --> [3, 2, 1][3].concat(reverseArr([1,2])), [2].concat(reverseArr([1])), [1].concat(reverseArr([ ]))가 되고 배열이 0인 경우 빈 배열을 리턴한다.
다시 정리하면, [1].concat([ ]) = [1], [2].concat([1]) = [2, 1], [3].concat([2, 1]) = [ 3, 2, 1 ]해서 최종적으로 [3, 2, 1]가 된다.
15_flattenArr
function flattenArr(arr) {
// 배열이 0인 경우 빈 배열을 리턴한다.
if(arr.length === 0){
return [];
}
//배열 안이 배열인 경우 재귀 함수를 통해 1차원 배열로 변환한다.
if(Array.isArray(arr[0])){
return flattenArr([...arr[0], ...arr.slice(1)]); // 전개 연산자
}
return [arr[0]].concat(flattenArr(arr.slice(1)));
}
let output = flattenArr([[1], 2, [3, 4], 5]);
console.log(output); // --> [1, 2, 3, 4, 5]
output = flattenArr([[2, [[3]]], 4, [[[5]]]]);
console.log(output); // --> [2, 3, 4, 5]flattenArr([1, [2, [3, 4], 5]]), [1].concat(flattenArr([2, [3, 4], 5])), [2].concat(flattenArr([[3, 4], 5])),
flattenArr([3, 4, [5]]), [3].concat(flattenArr([4, [5]])), [4].concat(flattenArr([5])),
flattenArr([5, [ ]])하고 배열이 0인 경우 빈 배열을 리턴한다.
[5], [4].concat([5]) = [4, 5], [3].concat([4, 5]) = [3, 4, 5], [2].concat([3, 4, 5]) = [2 ,3, 4, 5], [1].concat([2 ,3, 4, 5]) = [1, 2, 3, 4, 5]해서 최종적으로 [1, 2, 3, 4, 5]가 나온다.
참고)
전개 연산자( ... )를 사용하여 명시적으로 할당되지 않은 나머지 배열 값들을 사용할 수 있다.
[a1, a2, ...rest_a] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(a1); // 1
console.log(a2); // 2
console.log(rest_a); // [3, 4, 5, 6, 7, 8, 9]또 다른 풀이:
function flattenArr(arr) {
for(let i= 0; i < arr.length; i++) {
if(Array.isArray(arr[i])) {
let front = arr.slice(0, i);
let mid = arr[i];
let back = arr.slice(i+1);
let result = [...front, ...mid, ...back];
return faltterArr(result)
}
}
return arr
}