
def sum(n):
return n + sum(n-1)
→ 위 코드를 실행하면 오류가 난다
별도의 장치 없이 재귀함수를 실행하면 무한히 실행하게 되므로 종결 조건이 필수적으로 필요하다
def sum(n):
# 종결 조건
if n <= 1: return 1
else: return n + sum(n-1)
모든 재귀알고리즘은 그와 대칭되는 반복적인 알고리즘이 있다
즉, 재귀 알고리즘은 for, while과 같은 반복문을 통해 구현이 가능하다
재귀 알고리즘은 Recursive version, 반복문을 활용한 것은 Iterative version 이라고 한다
Recursive version
def sum(n):
# 종결 조건
if n <= 1: return 1
else: return n + sum(n-1)
→
Iterative version
def sum(n):
s = 0
while n >= 0:
s += n
n -= 1
return s
→
시간 복잡도가 아닌 효율성 측면에서 재귀 알고리즘은 함수를 호출할 수록 메모리를 차지하기 때문에 iterative version보다 떨어진다 (counter part)
수학 공식을 활용하면 상수 시간의 코드를 얻을 수 있다
def sum(n):
return n * (n+1) // 2
→
def what(n):
if n <= 1:
return 1
else:
return n * what(n-1)
→ 1부터 n까지 곱한다 ⇒
팩토리얼은 개념 자체가 재귀적이기 때문에 재귀함수를 이해하기에 좋다

recursive version
def fib(n):
if n <= 0: return 0
elif n <= 2: return 1
else: return fib(n-2) + fib(n-1)
iterative version
def fib(n):
a, b = 0, 1
for i in range(n):
a, b = b, a+b
return a
문제: n개의 서로 다른 원소에서 m개를 택하는 경우의 수
공식을 활용하는 방법
from math import factorial as f
def combi(n, m):
return f(n) / (f(m) * f(n-m))
재귀적 방법으로 구하기
n-1개의 서로 다른 원소에서 m개를 택하는 경우의 수와 n-1개의 서로 다른 원소에서 m-1개를 택하는 경우의 수를 더한 것과 같다
즉, n-1개의 1개를 포함해 고르는 경우(n-1개 중 m-1), 포함하지 않고 고르는 경우(n-1개 중 m개)를 따로 계산하는 것
# Trivial case를 고려하지 않은 코드
def combi(n, m):
return combi(n-1, m) + combi(n-1, m-1)
# Trivial case를 고려한 코드
def combi(n, m):
# 모든 것을 골라야하는 경우
if n == m: return 1
# 고를 것이 없는 경우
elif m == 0: return 1
return combi(n-1, m) + combi(n-1, m-1)
combi()를 두 번 호출하기 때문에 효율성 측면에서 좋지 않다
→ iterative version이 더욱 효율적인 경우
# 수업에서 나온 코드
def fib(n):
elif n <= 2: return n
else: return fib(n-2) + fib(n-1)

동일한 작업이 여러번 발생한다는 비효율적인 측면이 있다
→ 숫자가 커질수록 iterative version이 더 효율적이다
def binsearch(L, x, lower, upper):
if upper < lower:
return -1
middle = (lower + upper)//2
if x == L[mid]:
return mid
elif x < L[mid]:
return binsearch(L, x, lower, middle-1)
else:
return binsearch(L, x, middle+1, upper)