-
๐๏ธ ์๊ณ ๋ฆฌ์ฆ | ์ฌ๊ท ํจ์(Recursion), ํผ๋ณด๋์น ์algorithm 2020. 7. 23. 18:26
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)์ด๋ค.
[์ฐธ๊ณ ์๋ฃ]