intro
๐ ์ฌ๊ทํจ์๋, ์๊ธฐ ์์ ์ ๋ค์ ํธ์ถํ๋ ํจ์์ด๋ค. ํจ์ ๋ด์ ๋ค์ ํจ์๋ฅผ ๋ถ๋ฌ์, ๋์ผ ํจ์ ๋ก์ง์ ๋ฐ๋ณต์ ์ผ๋ก(์ฌ๊ท์ ) ์งํํ๋ค. DFS ๊ตฌํ์ ์ํด ์์ฃผ ์ฌ์ฉ๋๋ ๊ฐ๋ . ์๋ ์ฝ๋ ์์ ์ฐธ์กฐ.
def recursive_function():
print('recursive call')
recursive_function()
recursive_function()
→ ๋ฌดํํ ์ถ๋ ฅ๋๋ค๊ฐ python์ ๊ฒฝ์ฐ 'RecursionError: maximum recursion depth exceeded while calling a Python object'๋ผ๋ ๋ฉ์์ง ์ถ๋ ฅ - ์ฌ๊ท ์ต๋ ํ์ฉ ๊น์ด๊ฐ ์์ด ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋์ ์ถ๋ ฅ๋๋ฉฐ ์ข ๋ฃ. ํจ์๋ฅผ ๋ถ๋ฅผ ๋ ๋ง๋ค ์คํ ์๋ฃ ๊ตฌ์กฐ์ ํจ์๊ฐ ๊ณ์ ์์ด๋ฉด์ ์ปดํจํฐ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌ๊ฐ ๋๋ค. ๋ฐ๋ผ์, ๋ฉ๋ชจ๋ฆฌ๋ ํ๊ณ๊ฐ ์์ผ๋ฏ๋ก ์ฌ๊ท ๊น์ด ์ ํ์ ๋์จํ๊ฒ ํ๊ฑฐ๋, ๋ณ๋ ์คํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์๋ค. ์ฌ๊ท๋ ์ฌ๋ฌ ๋ฌธ์ ๋ฅผ ํ๋ฉด์ ์ต์ํด์ง๊ณ ์ ์ํ๋ ๊ฒ BEST. ์ฌ๊ทํจ์๋ฅผ ์ ํ์ฉํ๋ฉด ๋ณต์กํ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ ์ ์๋ค. (๋จ, ์คํ๋ ค ๋ค๋ฅธ ์ฌ๋์ด ์ดํดํ๊ธฐ ์ด๋ ค์ด ํํ์ ์ฝ๋๊ฐ ๋ ์ ์์ผ๋ฏ๋ก ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํจ!) ๋ํ ๋ชจ๋ ์ฌ๊ทํจ์๋ ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํ์ฌ ๋์ผํ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ (์ญ๋ ๊ฐ๋ฅ) / ์ฌ๊ทํจ์๊ฐ ๋ฐ๋ณต๋ฌธ๋ณด๋ค ์ ๋ฆฌํ ๊ฒฝ์ฐ๋, ๋ถ๋ฆฌํ ๊ฒฝ์ฐ๋ ์๋ค. (๋ฌธ์ ์ํฉ๋ณ๋ก ๊ตฌ๋ณ) ์ปดํจํฐ๊ฐ ํจ์๋ฅผ ์ฐ์์ ์ผ๋ก ํธ์ถํ๋ฉด ์ปดํจํฐ ๋ฉ๋ชจ๋ฆฌ ๋ด๋ถ์ ์คํ ํ๋ ์์ ์์ (๋ฐ๋ผ์ ์คํ์ ์ฌ์ฉํด์ผ ํ ๋ ๊ตฌํ์ ์คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋์ ์ ์ฌ๊ทํจ์๋ฅผ ์ด์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค - ๋ํ์ ์ผ๋ก DFS๋ฅผ ๋ ๊ฐ๊ฒฐํ๊ณ ์งง์ ์ฝ๋๋ก ๊ตฌํํ๊ธฐ ์ํด ์ฌ๊ทํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์) divide & conquer, DP, backtracking, DFS ๋ฑ ๋ค์ํ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉ๋๋ recursion ํ์ ์์ง! (ex ํ๋ ธ์ด ํ, Tree Traversal(Inorder, preorder, postorder)
→ Recursion helps in logic building. Recursive thinking helps in solving complex problems by breaking them into smaller subproblems.
→ Steps
โ define a base case: Identify the simplest (or base) case for which the solution is known or trivial. This is the stopping condition for the recursion, as it prevents the function from infinitely calling itself.
โก define a recursive case: Define the problem in terms of smaller subproblems. Break the problem down into smaller versions of itself, and call the function recursively to solve each subproblem.
โข Ensure the recursion terminates: Make sure that the recursive function eventually reaches the base case, and does not enter an infinite loop.
โฃ Combine the solutions: Combine the solutions of the subproblems to solve the original problem.
→ stack ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ ์ด์ : stack์ LIFO(Last-In First-Out) ๊ตฌ์กฐ์ด๋ฏ๋ก ๊ฐ์ฅ ์ต๊ทผ์ ์คํ๋ recursive function์ด ๋จผ์ ์คํ๋๊ธฐ ๋๋ฌธ์ ์ค์ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ์ stack ๋ฉ๋ชจ๋ฆฌ์ ํจ์ ํธ์ถ ๋๋ง๋ค ์ ์ฌ๋๋ค.
(When any function is called from main(), the memory is allocated to it on the stack. A recursive function calls itself, the memory for a called function is allocated on top of memory allocated to the calling function and a different copy of local variables is created for each function call. When the base case is reached, the function returns its value to the function by whom it is called and memory is de-allocated and the process continues)
→ disadvantages
โ recursive programs typically have more space requirements / more time to maintain the recursion call stack
โก recursion can make the code more difficult to understand & debug(it requires thinking about multiple levels of function calls)
→ advantages
โ provides a clean & simple way to write code
implementation
๐ ์ฌ๊ทํจ์๋ฅผ ๋ฌธ์ ํ์ด์์ ์ฌ์ฉํ ๋๋ ์ฌ๊ทํจ์์ ์ข ๋ฃ ์กฐ๊ฑด์ ๋ฐ๋์ ๋ช ์ํด์ผ ํ๋ค. ์ข ๋ฃ ์กฐ๊ฑด์ ๋ช ์ํ์ง ์์ผ๋ฉด RecursionError ๋ฐ์ํ๊ณ ํจ์๊ฐ ๋ฌดํํ ํธ์ถ. ์๋ ์์ ๋ฅผ ์ฐธ์กฐ
def recursive_function(i):
if i == 5:
return #recursion end
print(i,'th recursion function calls', i+1, 'the recursion function')
recursive_function(i+1)
print(i,'th recursion function ends')
recursive_function(1)
๐ ๋ง์น ์คํ์ฒ๋ผ, ํจ์์ ๋ํ ์ ๋ณด๊ฐ ์คํ ํ๋ ์์ ์์ด๋ฉด์ ์ฐจ๋ก๋๋ก ํธ์ถ๋๋ค๊ฐ ๊ฐ์ฅ ๋ง์ง๋ง์ ํธ์ถ๋ ํจ์๋ถํฐ ์ฐจ๋ก๋๋ก ์ข ๋ฃ. ์๋ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํ์. ๊ฐ์ฅ ๋จผ์ ํธ์ถ๋๋ ์ฌ๊ท ํจ์๊ฐ ๋งจ ์ฒ์๊ณผ ๋์ ๋ด๋น. ๊ทธ ๋ค์ ํธ์ถ๋๋ ์ฌ๊ท ํจ์๊ฐ ๋ ๋ฒ์งธ ์ฒ์๊ณผ ๋์ ๋ด๋น..... ์ด๋ ๊ฒ ๊ณ์ ๋ด๋ถ๋ก ์งํ. ๋งจ ๋ง์ง๋ง ํธ์ถ๋๋ ์ฌ๊ทํจ์์์ return ์ฒ๋ฆฌ. ์๋ ๊ทธ๋ฆผ ๊ธฐ์ค ์ค๋ฅธ์ชฝ์ผ๋ก ์งํ๋๋ ๋ฐฉํฅ์ด ๊บพ์ฌ์, recursive_function() ํธ์ถ ์ดํ ์๋ ์ฝ๋๊ฐ ์ฐจ๋ก๋๋ก ์งํ.
examples
โ factorial
def factorial_recursive(n):
if n<=1:
return 1
return n*factorial_recursive(n-1)
print(factorial_recursive(5))
โก euclidean algorithm
๐ ๋ ๊ฐ์ ์์ฐ์์ ๋ํ ์ต๋๊ณต์ฝ์๋ฅผ ๊ตฌํ๋ ๋ํ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก '์ ํด๋ฆฌ๋ ํธ์ ๋ฒ'์ด ์๋ค. ๋ ์์ฐ์ A,B์ ๋ํ์ฌ (A>B) A๋ฅผ B๋ก ๋๋ ๋๋จธ์ง๋ฅผ R์ด๋ผ๊ณ ํ์. ์ด ๋ A์ B์ ์ต๋๊ณต์ฝ์๋ B์ R์ ์ต๋๊ณต์ฝ์์ ๊ฐ๋ค. ์๋ ์ฌ๊ท ์ฝ๋ ์ฐธ์กฐ
a,b=map(int,input().split())
def gcd(a,b):
if b == 0:
return a
return gcd(b,a%b)
print(gcd(a,b))
๐งญ <BOJ S5 17478 ์ฌ๊ทํจ์๊ฐ ๋ญ๊ฐ์?>
Q. ํจ์ ์์ return๋ฌธ์ ๋จผ์ ๋ฃ๊ณ ๋์ผ ์ฌ๊ท ํจ์ ๋ฃ๊ธฐ ์ ๊ณผ ๋ค ๊ฐ๊ฐ print()๋ฌธ ์งํ
๐งญ <BOJ S3 4779 ์นธํ ์ด ์งํฉ>
Q. ํจ์ ์์ ์ฌ๊ทํจ์๊ฐ 2๊ฐ ์๋ ๋ฌธ์ . ๊ฐ์ด๋ฐ๋ ๋น์นธ์ผ๋ก ๋๋๊ณ ๋น์นธ ๊ธฐ์ค ์๊ณผ ๋ค ๊ฐ๊ฐ ์ฌ๊ทํจ์ ์งํ
๐งญ<BOJ B5 27433 ํฉํ ๋ฆฌ์ผ 2 + B2 10870 ํผ๋ณด๋์น ์ 5>
Q. ๋ ๋ฌธ์ ๋ชจ๋ ์ฌ๊ทํจ์๋ก๋ ํ ์ ์๋ ๋ฌธ์ .
๐งญ<BOJ B2 25501 ์ฌ๊ท์ ๊ท์ฌ>
Q. ์ฌ๊ทํจ์ ๋ด๋ถ์ return ์ข ๋ฃ ์กฐ๊ฑด 2๊ฐ + return๋ฌธ์ ๋ด๋ถ ์ฌ๊ทํจ์ ํธ์ถ
'Computer Science > Algorithms' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ Binary Search ๐ (2) | 2022.12.06 |
---|---|
understanding pesudo-code of QuickSort (0) | 2022.12.05 |
DFS / BFS (0) | 2022.10.14 |
Implementation (1) | 2022.09.21 |
Greedy (0) | 2022.09.12 |
๋๊ธ