๐น 11. Recursion & Dynamic programming
08. ์ฌ๊ท์ ๋์ ํ๋ก๊ทธ๋๋ฐ
์ฌ๊ท์ ๊ด๋ จ๋ ๋ฌธ์ ๋ค์ ์๋น์๋ ํจํด์ด ๋น์ทํ๋ค. ์ฃผ์ด์ง ๋ฌธ์ ๊ฐ ์ฌ๊ท ๋ฌธ์ ์ธ์ง ํ์ธํด ๋ณด๋ ๋ฐฉ๋ฒ์, ํด๋น ๋ฌธ์ ๋ฅผ ์์ ํฌ๊ธฐ์ ๋ฌธ์ ๋ก ๋ง๋ค ์ ์๋์ง ๋ณด๋ ๊ฒ์ด๋ค.
๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ฅ์ผ๋ก ์์ํ๋ ๋ฌธ์ ๋ ์ฌ๊ท๋ก ํ๊ธฐ ์ ๋นํ ๋ฌธ์ ์ผ ๊ฐ๋ฅ์ฑ์ด ๋๋ค.(ํญ์ ๊ทธ๋ฐ๊ฒ์ ์๋๋ค.)
- โn๋ฒ์งธ โฆ๋ฅผ ๊ณ์ฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ค๊ณํ๋ผโ
- โ์ฒซ n๊ฐ๋ฅผ ๋์ดํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ผโ
- โ๋ชจ๋ โฆ๋ฅผ ๊ณ์ฐํ๋ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ผโ
[ ์ ๊ทผ๋ฒ ]
์ฌ๊ท์ ํด๋ฒ์ ๋ถ๋ถ๋ฌธ์ (subproblem)์ ๋ํ ํด๋ฒ์ ํตํด ์์ฑ๋๋ค.
๋ฐ๋ผ์ ๋ง์ ๊ฒฝ์ฐ, ๋จ์ํ f(n-1)์ ๋ํ ํด๋ต์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ํ๊ฑฐ๋, ์ ๊ฑฐํ๊ฑฐ๋, ์๋๋ฉด ๊ทธ ํด๋ต์ ๋ณ๊ฒฝํ์ฌ f(n)์ ๊ณ์ฐํด๋ธ๋ค. ์๋๋ฉด, ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ผ๋ก ๋๋ ๊ฐ๊ฐ์ ๋ํด์ ๋ฌธ์ ๋ฅผ ํผ ๋ค ์ด ๋์ ๋ณํฉ(merge)ํ๊ธฐ๋ ํ๋ค.
์ฃผ์ด์ง ๋ฌธ์ ๋ฅผ ๋ถ๋ถ๋ฌธ์ ๋ก ๋๋๋ ๋ฐฉ๋ฒ๋ ์ฌ๋ฌ ๊ฐ์ง ์๋ค. ๊ฐ์ฅ ํํ๊ฒ ์ฌ์ฉ๋๋ ์ธ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก๋
- ์ํฅ์(bottom-up)
- ํํฅ์(top-down)
- ๋ฐ๋ฐ(half-and-half)
์ด ์๋ค.
์ํฅ์ ์ ๊ทผ๋ฒ
์ํฅ์ ์ ๊ทผ๋ฒ(bottom-up approach)๋ ๊ฐ์ฅ ์ง๊ด์ ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ์ด ์ ๊ทผ๋ฒ์ ์ฐ์ ๊ฐ๋จํ ๊ฒฝ์ฐ๋ค์ ๋ํ ํ์ด๋ฒ์ ๋ฐ๊ฒฌํ๋ ๊ฒ์ผ๋ก๋ถํฐ ์์ํ๋ค.
ex) ๋ฆฌ์คํธ
์ฒ์์๋ ์์ ํ๋๋ฅผ ๊ฐ๋ ๋ฆฌ์คํธ๋ก๋ถํฐ ์์ํ๋ค. ๋ค์์๋ ์์ ๋ ๊ฐ๊ฐ ๋ค์ด ์๋ ๋ฆฌ์คํธ์ ๋ํ ํ์ด๋ฒ์ ์ฐพ๊ณ , ๊ทธ ๋ค์์๋ ์ธ ๊ฐ ์์๋ฅผ ๊ฐ๋ ๋ฆฌ์คํธ์ ๋ํ ํ์ด๋ฒ์ ์ฐพ๋๋ค. ์ด๋ฐ ์์ผ๋ก ๊ณ์ํด ๋๊ฐ๋ค.
์ด ์ ๊ทผ๋ฒ์ ํต์ฌ์, ์ด์ ์ ํ์๋ ์ฌ๋ก๋ฅผ ํ์ฅํ์ฌ ๋ค์ ํ์ด๋ฅผ ์ฐพ๋๋ค๋ ์ ์ด๋ค.
ํํฅ์ ์ ๊ทผ๋ฒ
ํํฅ์ ์ ๊ทผ๋ฒ(top-down approach)๋ ๋ ๋ช ํํด์ ๋ณต์กํด ๋ณด์ผ ์ ์๋ค. ํ์ง๋ง ๊ฐ๋์ ์ด ๋ฐฉ๋ฒ์ด ๋ฌธ์ ์ ๋ํด ์๊ฐํด ๋ณด๊ธฐ์ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด๊ธฐ๋ ํ๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ค์ ์ด๋ป๊ฒ ํ๋ฉด N์ ๋ํ ๋ฌธ์ ๋ฅผ ๋ถ๋ถ ๋ฌธ์ ๋ก ๋๋ ์ ์์์ง ์๊ฐํด ๋ด์ผ ํ๋ค. ๋๋ ๋ถ๋ถ๋ฌธ์ ์ ๊ฒฝ์ฐ๊ฐ ์๋ก ๊ฒน์น์ง ์๋๋ก ์ฃผ์ํ๋ค.
๋ฐ๋ฐ ์ ๊ทผ๋ฒ
๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ผ๋ก ๋๋๋ ๋ฐฉ๋ฒ๋ ์ข ์ข ์ ์ฉํ๋ค.
ex) ์ด์ง ํ์
์ ๋ ฌ๋ ๋ฐฐ์ด์์ ํน์ ์์๋ฅผ ์ฐพ์ ๋, ๊ฐ์ฅ ๋จผ์ ์ผ์ชฝ ์ ๋ฐ๊ณผ ์ค๋ฅธ์ชฝ ์ ๋ฐ ์ค ์ด๋๋ฅผ ๋ด์ผ ํ๋์ง ํ์ธํ๋ค. ์ด์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ๋ฐ์ฉ ์ฌ๊ท์ ์ผ๋ก ํ์ํด ๋๊ฐ๋ค.
ex) ๋ณํฉ ์ ๋ ฌ
๋ฐฐ์ด ์ ๋ฐ์ ๊ฐ๊ฐ ์ ๋ ฌํ ๋ค ์ด๋ค์ ํ๋๋ก ๋ณํฉํ๋ค.
[ ์ฌ๊ท์ ํด๋ฒ vs ์ํ์ ํด๋ฒ ]
์ฌ๊ท์ ์๊ณ ๋ฆฌ์ฆ
โ ๊ณต๊ฐ ํจ์จ์ฑ์ด ๋๋น ์ง ์ ์๋ค.
์ฌ๊ท ํธ์ถ์ด ํ ๋ฒ ๋ฐ์ํ ๋๋ง๋ค ์คํ์ ์๋ก์ด ์ธต(layer)์ ์ถ๊ฐํด์ผ ํ๋ค. ์ด๋ ์ฌ๊ท์ ๊น์ด๊ฐ n์ผ ๋ O(n) ๋งํผ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ด๋ฐ ์ด์ ๋ก, ์ฌ๊ท์ (recursive) ์๊ณ ๋ฆฌ์ฆ์ ์ํ์ (iterative)์ผ๋ก ๊ตฌํํ๋ ๊ฒ์ด ๋ ๋์ ์ ์๋ค. ๋ชจ๋ ์ฌ๊ท์ ์๊ณ ๋ฆฌ์ฆ์ ์ํ์ ์ผ๋ก ๊ตฌํ๋ ์ ์์ง๋ง, ์ํ์ ์ผ๋ก ๊ตฌํ๋ ์ฝ๋๋ ๋๋ก ํจ์ฌ ๋ ๋ณต์กํ๋ค.
[ ๋์ ๊ณํ๋ฒ & ๋ฉ๋ชจ์ด์ ์ด์ ]
๋์ ํ๋ก๊ทธ๋๋ฐ์ ๊ฑฐ์ ๋๋ถ๋ถ ์ฌ๊ท์ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ฐ๋ณต์ ์ผ๋ก ํธ์ถ๋๋ ๋ถ๋ถ๋ฌธ์ ๋ฅผ ์ฐพ์๋ด๋ ๊ฒ์ด ๊ด๊ฑด์ด๋ค. ์ด๋ฅผ ์ฐพ์ ๋ค์๋ ๋์ค์ ์ํด ํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅํด ๋์ผ๋ฉด ๋๋ค.
ํน์ ์ฌ๊ท ํธ์ถ์ ํจํด์ ์ํ์ ํํ๋ก ๊ตฌํํ ์๋ ์๋ค. ๋ฌผ๋ก ์ฌ์ ํ ๊ฒฐ๊ณผ๋ฅผ โ์บ์โ์ ์ ์ฅํด์ผ ํ๋ค.
- ๋ฉ๋ชจ์ด์ ์ด์ (memoization) : ํํฅ์ ๋์ ํ๋ก๊ทธ๋๋ฐ
- ๋์ ํ๋ก๊ทธ๋๋ฐ : ์ํฅ์ ์ ๊ทผ๋ฒ
๋์ ํ๋ก๊ทธ๋๋ฐ์ ๊ฐ์ฅ ๊ฐ๋จํ ์์๋ n๋ฒ์งธ ํผ๋ณด๋์น ์(Fibonacci number)๋ฅผ ์ฐพ๋ ๊ฒ์ด๋ค. ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํ ๋๋ ์ผ๋ฐ์ ์ธ ์ฌ๊ท๋ก ๊ตฌํํ ๋ค ์บ์ ๋ถ๋ถ์ ๋์ค์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข๋ค.
ํผ๋ณด๋์น ์์ด
ํผ๋ณด๋์น ์๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ
๋ฐฉ๋ฒ #1: ์ฌ๊ท
1
2
3
4
5
int fibonacci(int i) {
if (i == 0) return 0;
if (i == 1) return 1;
return fibonacci(i - 1) + fibonacci(i - 2);
}
์ด ํจ์์ ์ํ ์๊ฐ์ ๊ณ ๋ คํ ๋ ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ์ฌ๊ท ๋ฌธ์ ๋ฅผ ํ ๋ ํธ์ถ๋๋ ๊ฒฝ๋ก๋ฅผ ํธ๋ฆฌ๋ก ๊ทธ๋ ค๋ณด๋ฉด ๋์์ด ๋๋ค.
ํธ๋ฆฌ์ ๋ง๋จ ๋ ธ๋๋ ๋ชจ๋ ๊ธฐ๋ณธ ๊ฒฝ์ฐ(base case)์ธ fib(1) ์๋๋ฉด fib(0)์ธ ๊ฒ์ ์ ์ ์๋ค. ๊ฐ ํธ์ถ์ ์์๋๋ ์๊ฐ์ด O(1) ์ด๋ฏ๋ก ํธ๋ฆฌ์ ์ ์ฒด ๋ ธ๋์ ๊ฐ์์ ์ํ ์๊ฐ์ ๊ฐ๋ค. ๋ฐ๋ผ์ ์ด ํธ์ถ ํ์๊ฐ ์ํ ์๊ฐ์ด ๋๋ค.
๊ธฐ๋ณธ ๊ฒฝ์ฐ(๋ง๋จ ๋ ธ๋)์ ๋๋ฌํ๊ธฐ ์ ๊น์ง์ ๊ฐ ๋ ธ๋๋ ๋ ๊ฐ์ ์์ ๋ ธ๋๋ฅผ ๊ฐ๊ณ ์๋ค. ์ด ์์ ๋ ธ๋ ๋ํ ๋ ๊ฐ์ ์์ ๋ ธ๋๋ฅผ ๊ฐ๊ณ ์๊ณ (์ฆ, ๋ค ๊ฐ์ ์์ ๋ ธ๋๊ฐ ์๋ ์ ์ด๋ค), ์ด ์์ ๋ ธ๋๋ค๋ ๊ฐ๊ฐ ๋ ๊ฐ์ ์์ ๋ ธ๋๋ฅผ ๊ฐ๊ณ ์๋ค.
์ด๋ฅผ n๋ฒ ๋ฐ๋ณตํ๋ฉด ๋๋ต $O(2^n)$๊ฐ์ ๋ ธ๋๋ฅผ ๊ฐ๊ฒ ๋๋ค. ๋ฐ๋ผ์ ์ํ ์๊ฐ์ ๋์ถฉ $O(2^n)$์ด ๋๋ค.
์ค์ ๋ก $O(2^n)$๋ณด๋ค ๋น ๋ฅด๋ค. ์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด (๋ง๋จ ๋ ธ๋์ ๋ง๋จ ๋ ธ๋ ๋ฐ๋ก ์๋ ์ ์ธํ๊ณ ) ์ค๋ฅธ์ชฝ ๋ถ๋ถํธ๋ฆฌ์ ํฌ๊ธฐ๊ฐ ์ผ์ชฝ ๋ถ๋ถํธ๋ฆฌ์ ํฌ๊ธฐ๋ณด๋ค ํญ์ ์๋ค๋ ์ฌ์ค์ ์ ์ ์๋ค. ๋ง์ฝ ์ด ๋์ ํฌ๊ธฐ๊ฐ ๊ฐ๋ค๋ฉด ์ํ ์๊ฐ์ $O(2^n)$์ด ๋ ๊ฒ์ด๋ค.
ํ์ง๋ง ์์ชฝ์ ํฌ๊ธฐ๊ฐ ๊ฐ์ง ์์ผ๋ฏ๋ก, ์ค์ ์ํ ์๊ฐ์ $O(1.6^n)$์ ๊ฐ๊น๋ค. big-O ํ๊ธฐ๋ฒ์ ์ํ ์๊ฐ์ ์ํ์ ์๋ฏธํ๋ ๊ฒ์ด๋ฏ๋ก $O(2^n)$๋ ๊ธฐ์ ์ ์ผ๋ก ์ณ์ ํํ๋ฒ์ด๊ธด ํ๋ค. ์ด์จ๋ ์ฌ์ ํ ์ํ ์๊ฐ์ ์ง์ ์๊ฐ์ด๋ค.
(์ง์ ์๊ฐ์ ์ํ ์๊ฐ์ด ๊ธฐํ๊ธ์์ ์ผ๋ก ์ฆ๊ฐํ๋ค.)
์ต์ ํ ๋ฐฉ๋ฒ์ ์ฐพ์์ผ ํ๋ค.
๋ฐฉ๋ฒ #2: ํํฅ์ ๋์ ํ๋ก๊ทธ๋๋ฐ(๋ฉ๋ชจ์ด์ ์ด์ )
์ฌ๊ท ํธ๋ฆฌ์์ ๋ง์ ๋ ธ๋๋ค์ด ์ค๋ณต๋์ด ํธ์ถ๋๋ค. ์ด๋ค์ด ํธ์ถ๋ ๋๋ง๋ค ๋ค์ ๊ณ์ฐํ ํ์๊ฐ ์๋ค.
์ฌ์ค, ์ฐ๋ฆฌ๊ฐ fib(n)์ ํธ์ถํ์ ๋, fib์ด ํ์ํ ๊ฒฝ์ฐ์ ์๊ฐ O(n)์ด๋ฏ๋ก fib ํจ์๋ฅผ O(n)๋ฒ ์ด์ ํธ์ถํ๋ฉด ์๋๋ค. ๋งค๋ฒ fib(i)๋ฅผ ๊ณ์ฐํ ๋๋ง๋ค ์ด ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅํ๊ณ ๋์ค์๋ ์ ์ฅ๋ ๊ฐ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค. ๋ฐ๋ก ์ด๊ฒ ๋ฉ๋ชจ์ด์ ์ด์ (memoization)์ด๋ค.
์ด์ ์ ์ฝ๋๋ฅผ ์ฝ๊ฐ ๊ณ ์ณ O(N) ์๊ฐ์ ๋์๊ฐ๊ฒ๋ ๋ง๋ ๋ค. ์ฌ๊ท ํธ์ถ ์ฌ์ด์ fibonacci(i)์ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅํ๋ ๋ถ๋ถ๋ง ์ถ๊ฐํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
int fibonacci(int n) {
return fibonacci(n, new int[n + 1]);
}
int fibonacci(int i, int[] memo) {
if (i == 0 || i == 1) return i;
if (memo[i] == 0) {
memo[i] = fibonacci(i - 1, memo) + fibonacci(i - 2, memo);
}
return memo[i];
}
์ผ๋ฐ์ ์ธ ์ปดํจํฐ์์ ์ด์ ์ ์ฌ๊ท ํจ์ ์ฝ๋๋ฅผ ๋๋ ค๋ณด๋ฉด 50๋ฒ์งธ ํผ๋ณด๋์น ์๋ฅผ ์ฐพ๋ ๋ฐ 1๋ถ ์ด์ ๊ฑธ๋ฆฐ๋ค. ํ์ง๋ง ๋์ ํ๋ก๊ทธ๋๋ฐ์ ์ฌ์ฉํ๋ฉด 10,000๋ฒ์งธ ํผ๋ณด๋์น ์์ด์ ์ฐพ๋ ๋ฐ ๋ฐ๋ฆฌ์ด(millisecond)๋ ๊ฑธ๋ฆฌ์ง ์๋๋ค(๋ฌผ๋ก ์์ ์ฝ๋๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉด 10,000๋ฒ์ด ๋๊ธฐ๋ ์ ์ int ์๋ฃํ ๋๋ฌธ์ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค)
์ฌ๊ท ํธ๋ฆฌ๋ฅผ ๊ทธ๋ ค๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.(์ฌ๊ฐํ์ผ๋ก ํ์๋ ๋ถ๋ถ์ ์บ์๊ฐ์ ๊ทธ๋๋ก ๋ฐํํ ๊ฒฝ์ฐ๋ฅผ ๋ํ๋ธ๋ค)
์ด ํธ๋ฆฌ์์ ๊ฐ ๋ ธ๋์ ์์ ๋ ธ๋๋ ํ ๊ฐ์ด๋ฏ๋ก, ๋ชจ๋ ๋ ธ๋์ ๊ฐ์๋ ๋๋ต 2n๊ฐ๊ฐ ๋๋ค. ๋ฐ๋ผ์ ์ํ ์๊ฐ์ O(n)์ด๋ค.
๋ฐฉ๋ฒ #3: ์ํฅ์ ๋์ ํ๋ก๊ทธ๋๋ฐ
์ฌ๊ท์ ์ธ ๋ฉ๋ชจ์ด์ ์ด์ ์ผ๋ก ์ ๊ทผํ๋ ๊ทธ๊ฒ์ ๋ค์ง๋๋ค๊ณ ์๊ฐํด๋ณด์.
๋จผ์ , ์ด๊ธฐ ์ฌ๋ก(base case)์ธ fib(1)๊ณผ fib(0)์ ๊ณ์ฐํ๋ค. ๊ทธ ๋ค, ์ด ๋์ ์ด์ฉํด fib(2)๋ฅผ ๊ณ์ฐํ๊ณ , ์ฐจ๋ก๋ก fib(3), fib(4) ๋ฑ์ ์ด์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ด์ฉํด ๊ณ์ฐํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
int fibonacci(int n) {
if (n == 0) return 0;
else if (n == 1) return 1;
int[] memo = new int[n];
memo[0] = 0;
memo[1] = 1;
for (int i = 2; i < n; i++) {
memo[i] = memo[i - 1] + memo[i - 2];
}
return memo[n - 1] + memo[n - 2];
}
memo[i]๋ memo[i+1]๊ณผ memo[i+2]๋ฅผ ๊ณ์ฐํ ๋๋ง ์ฌ์ฉ๋ ๋ฟ, ๊ทธ ๋ค์๋ ์ ํ ์ฌ์ฉ๋์ง ์๋๋ค. ๋ฐ๋ผ์ memo ํ ์ด๋ธ ๋ง๊ณ ๋ณ์ ๋ช ๊ฐ๋ฅผ ์ฌ์ฉํด์ ํ ์๋ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
int fibonacci(int n) {
if (n == 0) return 0;
int a = 0;
int b = 1;
for (int i = 2; i < n; i++) {
int c = a + b;
a = b;
b = c;
}
return a + b;
}
์ ์ฝ๋๋ ๋จ์ํ ํผ๋ณด๋์น ์์ด์ ๋ง์ง๋ง ์ซ์ ๋ ๊ฐ๋ฅผ a์ b ๋ณ์์ ์ ์ฅํ๋๋ก ๋ฐ๊พผ ๊ฒฐ๊ณผ๋ค. ๋ฃจํ์ ๊ฐ ๋จ๊ณ์์๋ ๋ค์ ๊ฐ (c = a + b)์ ๊ณ์ฐํ ๋ค (b, c = a + b)์ ๊ฐ์ (a, b)๋ก ์ฎ๊ธฐ๋ ์ผ์ ์ํํ๋ค.