ποΈ μκ³ λ¦¬μ¦ | μ¬κ· ν¨μ(Recursion), νΌλ³΄λμΉ μ
what is μ¬κ· ν¨μ
λ§μ μ¬λλ€μ΄ λ§μ§μμ λ°₯μ λ¨ΉκΈ° μν΄ μ€μ μ°λ€. νμ¬ λλ μ€μ 맨 λμ μμΉνκ³ μλ€. νμ¬ λ΄κ° λͺ λ²μ§Έλ‘ λκΈ°νκ³ μλμ§ μκ³ μΆλ€λ©΄ μ μ¬λμκ² λͺ λ²μ§ΈμΈμ§ λ¬Όμ΄λ³΄λ©΄ λλ€. λ§μ½ μ μ¬λμ΄ λͺ¨λ₯Έλ€λ©΄ μ μ¬λμ μμ μ μ μ¬λμκ² λ¬Όμ΄λ³΄κ³ μ΄ κ³Όμ μ΄ λ°λ³΅λ κ²μ΄λ€(첫 λ²μ§Έ λκΈ°μκΉμ§).
λλ μ μ¬λμκ² 'μ λ 5λ²μ΄μμ' λΌλ λλ΅μ λ€μλ€. κ·Έλ λ€λ©΄ λμ λκΈ°λ²νΈλ 5 + 1 = 6λ² μ΄λ€.
κ·Έ κ³Όμ μ μ½λλ₯Ό μμ±νλ©΄ μλμ κ°λ€.
function getMyPositionInLine(person){
if (person.nextInLine == null){
//μμ¬λ μ‘΄μ¬ x
return 1;
}
return 1 + getMyPositionInLine(person.nextInLine);
}
μ΄λ κ² ν¨μ μμμ μκΈ° μμ (ν¨μ)μ λ€μ νΈμΆνλ ν¨μλ₯Ό μ¬κ· ν¨μλΌκ³ νλ€.
μ¬κ· ν¨μ ꡬ쑰
μ¬κ· ν¨μμμλ μ‘°κ±΄λ¬Έμ΄ μ€μνλ€. 쑰건문 μμλ μ¬κ· ν¨μμ μ’ λ£ μ‘°κ±΄μ λ£μ΄μ£Όμ΄μΌ νλ€.
why we use μ¬κ· ν¨μ
μ¬κ· ν¨μλ for λ¬Έκ³Ό while λ¬ΈμΌλ‘ λμ²΄κ° κ°λ₯νλ€.
function recursion(someValue){
while(someValue < 10){
someValue += 1;
}
return ;
}
νμ§λ§ μλμ κ°μ΄ λ°°μ΄ μμ λ°°μ΄μ΄ λ€μ΄μκ³ λκ°μ λ‘μ§μ΄ λ°λ³΅λλ κ²½μ°μλ for λ¬Έμ΄ κ³μ μ€μ²©λ μ μλ€.
function recursionArr(array){
let sum = 0;
for(let i = 0; i < array.length; i++){
//λ§μ½ μμκ° λ°°μ΄μ΄λΌλ©΄
if (type of array[i] === 'array'){
for (let j = 0; j < array[i].length; j++){
//λ§μ½ μμκ° λ°°μ΄μ΄λΌλ©΄
if (type of array[i] === 'array'){
//... λ°λ³΅
}
}
}
else {
sum += array[i];
}
}
return sum;
}
recursionArr([1, [1,3, [1,2,4]]]);
μ¬κ· ν¨μλ₯Ό μ¬μ©ν κ²½μ°, μ½λλ₯Ό λ μ§κ΄μ μΌλ‘ κ°κ²°νκ² μ§€ μ μλ€.
function recursionArr(arr, sum){
for (let i = 0; i < arr.length; i++){
if (typeof arr[i] === 'number'){
sum += array[i];
} else {
return recursionArr(array[i], sum);
}
}
return sum;
}
recursionArr([1, [1,3, [1,2,4]]], 0);
Call Stack
μ½ μ€νμ μλ κ³Όμ μ λ€μκ³Ό κ°λ€.
function a(){
return "hello " + b();
};
function b(){
return "my " + c();
};
function c(){
return "friends.";
};
1. call stack μ "hello " + b() μμ μ΄ λ€μ΄κ°λ€.
2. ν¨μ aμμλ ν¨μ bλ₯Ό νΈμΆνκ³ μκΈ° λλ¬Έμ "my " + c() μμ μ΄ λ€μ΄κ°λ€.
3. ν¨μ bμμλ ν¨μ cλ₯Ό νΈμΆνκ³ μκΈ° λλ¬Έμ "friends ." μμ μ΄ λ€μ΄κ°λ€.
4. μμ λ€μ΄ μ€νλλ©΄μ μμ λ€μ΄ call stackμμ popλλ€(return).
μ¬κ· ν¨μμμ μ½ μ€νμ λ€μκ³Ό κ°λ€.
function a(){
return a();
}
μ’ λ£ μ‘°κ±΄μ΄ μμ κ²½μ° call stackμλ κ³μ ν¨μ a()κ° νΈμΆλμ΄ μμ΄κ² λλ€. μ½ μ€νμ΄ λμΉκ² λλ©΄ λ©λͺ¨λ¦¬ λΆμ‘±μΌλ‘ μλ¬κ° λ°μνλ€(stack overflow!).
꼬리 μ¬κ· μ΅μ ν(Tail Recursion)
μ¬κ· ν¨μμ κ²½μ°, λ°λ³΅λ¬Έμ λΉν΄ μκ°λ μ€λ κ±Έλ¦¬κ³ , μ€νμ΄ λμΉλ κ²½μ°κ° μκΈ΄λ€. μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λ§μ μΈμ΄λ€μ 꼬리 μ¬κ· μ΅μ νλΌλ κΈ°λ₯μ μ 곡νλ€.
꼬리 μ¬κ· μ΅μ νλ μ ν μκ³ λ¦¬μ¦μ λ§λ€μ΄ μ€ννκ² νλ€. μ ν μκ³ λ¦¬μ¦μ μκ°λ³΅μ‘λκ° O(n)μΈ μκ³ λ¦¬μ¦μ΄λ€. λλ¬Έμ μ½λκ° κ³μ μΆκ°λλλΌλ μ΅λ nλ²μ λ°λ³΅νκ² λλ€.
νΌλ³΄λμΉ μ(Fibonacci numbers)
νΌλ³΄λμΉ μλ F(0) = 0, F(1) = 1μ΄κ³ , nμ΄ 2 μ΄μ μΌλλ F(n) = F(n-1) + F(n-2) μΈ μμ΄μ΄λ€.
1, 1, 2, 3, 5, 8, ....
μ¬κ· ν¨μλ₯Ό μ΄μ©νμ¬ n λ²μ§Έ νΌλ³΄λμΉ μλ₯Ό μΆλ ₯νλ ν¨μλ₯Ό λ§λ€μ΄ 보μ.
1. Recursion
function fib(n){
let result = 0;
if (n === 1 && n === 2){
result = 1;
} else if (n >= 2){
result = fib(n-1) + fib(n-2);
}
return result;
};
5λ²μ§Έ νΌλ³΄λμΉ μλ₯Ό ꡬνλ κ²½μ°λ λ³ λ¬Έμ κ° μλ€κ³ νλλΌλ, λ§μ½ nμ΄ 100μ΄λ©΄ fibν¨μκ° μμ£Ό λ§μ΄ call stackμ μμ΄κ² λ κ²μ΄λ€.
νΌλ³΄λμΉ μλ₯Ό ꡬν λ μ¬κ· ν¨μλ₯Ό μ¬μ©νλ κ²½μ°, μκ°λ³΅μ‘λλ O(2^n) μ΄ λλ€.
μ΄μΈμλ νΌλ³΄λμΉ μμ΄μ νΈλ λ°©λ²μ΄ μ¬λ¬κ°μ§ μλ€.
2. Memoized solution(store)
fib(5) κ°μ ꡬν λ, fib(3)μ΄ λ°λ³΅μ μΌλ‘ νΈμΆλλ€. store λ°©μμ μ²μ fib(3)κ° νΈμΆλμμ λ, κ°μ κΈ°μ΅ν λ€μ λλ²μ§Έ fib(3)μ ꡬν λ κ·Έ κ°μ μ¬μ©νλ€.
function fib(n,memo){
if(memo[n] !== null){
return memo[n];
}
if (n === 1 || n === 2){
result = 1;
} else {
result = fib(n-1) + fib(n-2);
memo[n] = (result);
}
return result;
}
f (1) = 1, f(2) = 1, f(3) = 2... κ°λ€μ λ°°μ΄μμ λ£μλ€.
[1, 1, 2, ...]
λ§μ½ λ€μ f(3) κ°μ΄ νμν κ²½μ° memoμμ nλ²μ§Έ μΈλ±μ€ κ°μ 리ν΄νλ©΄ λλ€.
μ΄ κ²½μ°μλ μκ°λ³΅μ‘λκ° μ΅λ O(n)μ΄ λλ€.
3. Bottom-up Approach
function fib(n){
if (n === 1 || n === 2){
return 1;
} else {
let array = [];
array.push(1,1);
for(let i = 2; i < n; i++){
array.push(array[i-2] + array[i-1]);
}
}
return array[array.length - 1];
}
fib(1) λΆν° fib(n)κΉμ§μ κ°μ arrayμ μ μ₯μν€λ λ°©μμ΄λ€. fib(1) λΆν° fib(2)κΉμ§ μ±μλ£κ³ ([1,1]), fib(3) λΆν°λ fib(3-1) + fib(3-2) λ‘ κ°μ nκΉμ§ ꡬνλ λ°©μμ΄λ€.
μ΄ κ²½μ° μκ°λ³΅μ‘λλ O(n)μ΄λ€.
[μ°Έκ³ μλ£]