๊ด€๋ฆฌ ๋ฉ”๋‰ด

JiYoung Dev ๐Ÿ–ฅ

[ํŒŒ์ด์ฌ] ์žฌ๊ท€ ํ•จ์ˆ˜(Recursive Function) ๋ณธ๋ฌธ

python

[ํŒŒ์ด์ฌ] ์žฌ๊ท€ ํ•จ์ˆ˜(Recursive Function)

Shinjio 2023. 2. 18. 23:32

2023.02.18 ์ฝ”๋“œ์ž‡ ํ•™์Šต๋‚ด์šฉ ์ •๋ฆฌ

 

์žฌ๊ท€ (Recursion)

์žฌ๊ท€๋ž€ '์ž๊ธฐ ์ž์‹ ์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ'

 

์žฌ๊ท€ ํ•จ์ˆ˜ (Recursive Function) 

์ž๊ธฐ ์ž์‹ ์„ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜

 

์žฌ๊ท€ํ•จ์ˆ˜ ์˜ˆ1

 

๐Ÿ”Ž ํŒฉํ† ๋ฆฌ์–ผ

์žฌ๊ท€์ ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ‘ผ๋‹ค๋Š” ๊ฒƒ์€ ๊ฐ™์€ ํ˜•ํƒœ์˜ ๋” ์ž‘์€ ๋ฌธ์ œ(๋ถ€๋ถ„ ๋ฌธ์ œ ; sub problem)๋ฅผ ํ’€๊ณ  ๋ถ€๋ถ„ ๋ฌธ์ œ์˜ ๋‹ต์„ ์ด์šฉํ•ด์„œ ๊ธฐ์กด ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๊ฒƒ์„ ๋งํ•จ  

 

์•„๋ž˜์™€ ๊ฐ™์ด f(n)์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด f(n-1)์˜ ๊ฐ’์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๊ทœ์น™์„ ์ฐพ์•„์„œ ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๊ฒƒ

f(5) = 5! = 5 * 4 * 3 * 2 * 1 = 5 * 4! = 5 * f(4) 
f(4) = 4! = 4 * 3 * 2 * 1 = 4 * 3! = 4 * f(3)
f(3) = 3! = 3 * 2! = 3 * f(2)
...
f(n) = n! = n * (n-1)! = n * f(n-1)
๋‹จ, n=0์ผ ๊ฒฝ์šฐ๋Š” 1

 

์žฌ๊ท€ ํ•จ์ˆ˜ ๋ฌธ์ œ๋ฅผ ํ’€ ๋•Œ๋Š” ํ•ญ์ƒ base case์™€ recursive case๋กœ ๊ฒฝ์šฐ๋ฅผ ๋‚˜๋ˆ„์–ด์ฃผ์–ด์•ผ ํ•จ

base case ์ฆ‰, ํƒˆ์ถœ ์กฐ๊ฑด์ด ์žˆ์–ด์•ผ ํ•จ์ˆ˜๋ฅผ ๋๋‚ผ ์ˆ˜ ์žˆ์Œ

base case๋ž€ ๋ฌธ์ œ๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ž‘์•„์„œ ๋ฐ”๋กœ ํ’€ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ๋งํ•จ (๋”ฐ๋กœ ํ’€์–ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ)

์žฌ๊ท€ ํ•จ์ˆ˜์—์„œ base case๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š์œผ๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜์ง€ ์•Š์Œ

 

์œ„์˜ ํŒฉํ† ๋ฆฌ์–ผ ๋ฌธ์ œ์—์„œ

base case    :    n = 0์ธ๊ฒฝ์šฐ n! = 1 

recursive case   :    n > 0์ธ ๊ฒฝ์šฐ n! = (n-1)! X n

 

์žฌ๊ท€ํ•จ์ˆ˜ ์‚ฌ์šฉํ•˜์—ฌ ํŒฉํ† ๋ฆฌ์–ผ ํ’€๊ธฐ

 

๐Ÿ”Ž ์žฌ๊ท€ ํ•จ์ˆ˜ vs ๋ฐ˜๋ณต๋ฌธ

๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋Š” ์žฌ๊ท€ ํ•จ์ˆ˜๋กœ ํ’€ ์ˆ˜ ์žˆ๊ณ , ์žฌ๊ท€ ํ•จ์ˆ˜๋กœ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋Š” ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ํ’€ ์ˆ˜ ์žˆ์Œ

 

๊ทธ๋Ÿฌ๋‚˜ ์žฌ๊ท€ ํ•จ์ˆ˜์—๋„ ๋‹จ์ ์ด ์žˆ์Œ 

์žฌ๊ท€ ํ•จ์ˆ˜์—์„œ๋Š” ๋™์ผํ•œ ํ•จ์ˆ˜๋ฅผ ๊ณ„์†ํ•ด์„œ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ํ•จ์ˆ˜๋ฅผ ์œ„ํ•œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ณ„์†ํ•ด์„œ ํ• ๋‹น๋จ. ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์‚ฌ์šฉ๋˜๋Š” ์ž„์‹œ ์ €์žฅ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝœ ์Šคํƒ(call stack : ํ•จ์ˆ˜๊ฐ€ ๋๋‚œ ์œ„์น˜๋ฅผ ๊ธฐ๋กํ•ด ๋‘๋Š” ๊ฒƒ)์ด๋ผ๊ณ  ๋ถ€๋ฆ„. ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ฌดํ•œ๋ฃจํ”„์— ๋น ์ง€๊ฑฐ๋‚˜ ์žฌ๊ท€ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ๋„ˆ๋ฌด ๋งŽ์œผ๋ฉด ์ฝœ ์Šคํƒ์ด ์Œ“์ด๋ฉด์„œ ์Šคํƒ ๊ณต๊ฐ„์ด ์ดˆ๊ณผ๋˜๋Š” ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ ์˜ค๋ฅ˜ (StackOverflowError)๊ฐ€ ๋ฐœ์ƒ. ํŒŒ์ด์ฌ์—์„œ๋Š” ์ฝœ ์Šคํƒ์„ 1000๊ฐœ ๊นŒ์ง€๋งŒ ํ—ˆ์šฉํ•จ

 

๋ฐ˜๋ณต๋ฌธ์„ ์“ฐ๋Š” ๊ฒŒ ๋” ๊น”๋”ํ•˜๊ฑฐ๋‚˜ ํšจ์œจ์ ์ผ ๋•Œ๊ฐ€ ์žˆ๊ณ , ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ์“ฐ๋Š” ๊ฒŒ ๋” ๊น”๋”ํ•˜๊ฑฐ๋‚˜ ํšจ์œจ์ ์ผ ๋•Œ๊ฐ€ ์žˆ๋Š”๋ฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๊ณ , ์ฝœ์Šคํƒ์ด ์Œ“์ด๋Š” ๋ฌธ์ œ๊ฐ€ ์˜ˆ์ƒ๋˜๋ฉด ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉ

 

๐Ÿ”Ž ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด

์žฌ๊ท€ ํ•จ์ˆ˜ ์ž‘๋™ FLOW

i == 1 : fib(1)
return 1

i == 2 : fib(2)
return 1

i == 3 : fib(3)
fib(1) + fib(2) = 1 + 1 = 2

i == 4 : fib(4)
fib(2) + fib(3) = 1 + 2 = 3

...

i == 10 : fib(10)
fib(8) + fib(9) = 55

์ฝ˜์†” ์ถœ๋ ฅ๊ฐ’

1
1
2
3
...
55

 

๐Ÿ”Ž n์˜ ๊ฐ ์ž๋ฆฟ์ˆ˜์˜ ํ•ฉ ๊ตฌํ•˜๊ธฐ

โ–ผโ–ผ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ : sum_counts ๋ฅผ ์žฌ๊ท€ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉ

์ˆซ์ž n์„ ๋ฌธ์ž์—ด n์œผ๋กœ ๋ณ€ํ™˜ → str_n
n์˜ ์ž๋ฆฟ์ˆ˜ ๊ณ„์‚ฐ → count_digits
 
๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•œ n์˜ ๋งจ ๋’ท์ž๋ฆฌ์—์„œ๋ถ€ํ„ฐ์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜ : sum_counts
base case : 1์ž๋ฆฟ์ˆ˜ ์ผ๋•Œ (count_digits == 1์ผ ๊ฒฝ์šฐ)์—๋Š” str_n[0] return
recursive case : 2์ž๋ฆฟ์ˆ˜ ์ด์ƒ์ธ ๊ฒฝ์šฐ ๊ฐ ์ž๋ฆฟ์ˆ˜์˜ ํ•ฉ ๋”ํ•˜๊ธฐ

sum_digits(n)์— ๋Œ€ํ•˜์—ฌ sum_counts(์ž๋ฆฟ์ˆ˜) return  

์˜ˆ :

n = 22541

str_n = "22541"
count_digits = 5

sum_counts(5) return

sum_counts(4) + int("22541"[4]) = sum_counts(4) + 1 = 13 + 1 = 14
sum_counts(3) + int("22541"[3]) = sum_counts(3) + 4 = 9 + 4 = 13
sum_counts(2) + int("22541"[2]) = sum_counts(1) + 5 = 4 + 5 = 9
sum_counts(1) + int('22541"[1]) = 2+2 = 4
sum_counts(1) = int("22541"[0]) = 2

(ํŒŒ๋ž€์ƒ‰์€ ์œ—๋ฐฉํ–ฅ์œผ๋กœ ์ง„ํ–‰๋˜๋Š” ๊ณผ์ •)

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ

 

โ–ผโ–ผ ๋ชจ๋ฒ” ๋‹ต์•ˆ : // ์™€ % ํ™œ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Œ

base case
n์ด 10๋ณด๋‹ค ์ž‘์œผ๋ฉด n return

recursive case
sum_digits(22541) → 22541 % 10 + sum_digits(22541 // 10) = 1 + sum_digits(2254) = 1 + 13 = 14
sum_digits(2254) → 2254 % 10 + sum_digits(2254 // 10) = 4 + sum_digits(225) = 4 + 9 = 13
sum_digits(225) → 225 % 10 + sum_digits(225 // 10) = 5 + sum_digits(22) = 5 + 4 = 9
sum_digits(22) → 22 % 10 + sum_digits(22 // 10) =  2 + sum_digits(2) = 2 + 2 = 4
sum_digits(2) → 2 return

๋ชจ๋ฒ”๋‹ต์•ˆ

 

 

๐Ÿ”Ž ๋ฆฌ์ŠคํŠธ ๋’ค์ง‘๊ธฐ

๊ทœ์น™ ์ฐพ๊ธฐ
some_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]

9 + [1, 2, 3, 4, 5, 6, 7, 8 ๋’ค์ง‘๊ธฐ]
      8 + [1, 2, 3, 4, 5, 6, 7 ๋’ค์ง‘๊ธฐ]
             7 + [1, 2, 3, 4, 5, 6 ๋’ค์ง‘๊ธฐ]
                    ...
                        2 + [1 ๋’ค์ง‘๊ธฐ]

[ ๋’ค์ง‘๊ธฐ] → flip(some_list[ :1]

 

๐Ÿ”Ž ํ•˜๋…ธ์ด์˜ ํƒ‘

๊ทœ์น™์ฐพ๊ธฐ

๊ธฐ๋‘ฅ์€ ์ด 3๊ฐœ → start_peg = 1, end_peg = 2

๋งŒ์•ฝ ์›ํŒ์ด ์—†๋‹ค๋ฉด, ํ•จ์ˆ˜๋Š” ๊ทธ๋Œ€๋กœ ๋๋‚จ
if num_disks == 0 : return

์›ํŒ์ด 1๊ฐœ๋ผ๋ฉด,
1๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™

์›ํŒ์ด 2๊ฐœ๋ผ๋ฉด,
1๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 2๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™
2๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™
1๋ฒˆ ์›ํŒ์„ 2๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™

์›ํŒ์ด 3๊ฐœ๋ผ๋ฉด,
1๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™
2๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 2๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™
1๋ฒˆ ์›ํŒ์„ 3๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 2๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™    → ์›ํŒ 2๊ฐœ์ผ ๋•Œ์™€ ๊ฐ™์Œ. ๋‹จ 2๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ๋งŒ ๋‹ค๋ฆ„

3๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™
1๋ฒˆ ์›ํŒ์„ 2๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 1๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™    → ์›ํŒ 2๊ฐœ์ผ ๋•Œ์™€ ๊ฐ™์Œ. ๋‹จ 2๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•จ

2๋ฒˆ ์›ํŒ์„ 2๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™
1๋ฒˆ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ์œผ๋กœ ์ด๋™

...

์›ํŒ์ด num_disks๋ผ๋ฉด,
1๋ฒˆ๋ถ€ํ„ฐ num_disks - 1๋ฒˆ๊นŒ์ง€์˜ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ(start_peg)์—์„œ 2๋ฒˆ ๊ธฐ๋‘ฅ(other_peg)์œผ๋กœ ์ด๋™
num_disks์˜ ์›ํŒ์„ 1๋ฒˆ ๊ธฐ๋‘ฅ(strart_peg)์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ(end_peg)์œผ๋กœ ์ด๋™
1๋ฒˆ๋ถ€ํ„ฐ num_disks - 1๋ฒˆ๊นŒ์ง€์˜ ์›ํŒ์„ 2๋ฒˆ ๊ธฐ๋‘ฅ(other_peg)์—์„œ 3๋ฒˆ ๊ธฐ๋‘ฅ(end_peg)์œผ๋กœ ์ด๋™

์ด๋ฅผ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋ฉด,

hanoi(num_disks - 1, start_peg, other_peg)
move_disk(num_disks, strat_peg, end_peg)
hanoi(num_disks - 1, other_peg, end_peg)

์—ฌ๊ธฐ์„œ start_peg = 1, end_peg = 3, other_peg = 2 → ์„ธ ๊ฐœ์˜ ํ•ฉ์€ 6
๋”ฐ๋ผ์„œ other_peg = 6 - start_peg - end_peg

์‹คํ–‰ ๊ณผ์ • ์ •๋ฆฌ