[알고리즘][Recursion] 재귀(Recursion) 기본 개념과 예제 1
2021. 12. 21. 15:13ㆍAlgorithm
Recursion
재귀(Recursion)란 자기 자신을 호출하는 함수를 의미한다.
void func(...)
{
...
func(...);
...
}
하지만 아래와 같이 recursion은 무한루프에 갇힐 수 있다.
public static void func()
{
System.out.println("hello func!");
func();
}
hello func!
hello func!
hello func!
hello func!
...
...
Recursion이 항상 무한루프에 빠지지는 않는다. Recursion이 적절한 구조를 가지고 있다면 무한루프에 빠지지 않는다.
- Base Case : 적어도 하나의 recursion에 빠지지 않는 경우가 존재해야 한다.
- Recursive Case : recursion을 반복하다보면 결국 base case로 수렴해야 한다.
예제1 - 0~n까지의 합계 구하기
// 0~n까지의 합계를 재귀적으로 구함
public static int func(int n)
{
if(n==0) // base case : n==0
{
return 0;
}
return n + func(n-1); // recursive case : n>0
}
// 0~n까지의 합을 구함
@Test
void sumTest() {
System.out.println("sum Test");
System.out.println(Main.func(5));
}
15
recursion의 해석
- 이 함수의 목적은 0~n까지의 합을 구하는 것
- n==0이라면 합은 0
- n이 0보다 크다면 0~n까지의 합은 0에서 n-1까지의 합에 n을 더한 것
순환함수와 수확적 귀납법
- 정리
- func(int n)은 음이 아닌 정수 n에 대해서 0에서 n까지의 합을 올바르게 계산
- 증명
- n=0인 경우: 0을 반환한다. 올바르다.
- 임의의 양의 정수 k에 대해서 n<k인 경우 0에서 n까지의 합을 올바르게 계산하여 반환한다고 가정
- n=k인 경우 : func은 먼저 func(k-1)를 호출하는데 2번의 가정에 의해서 0에서 k-1까지의 합이 올바르게 계산되어 반환된다. 메서드 func은 그 값에 n을 더해서 반환하므로 결국 0에서 k까지의 합을 올바르게 계산하여 반환한다
Factorial: n!
- 0! = 1
- n! = n * (n-1)! (n>0)
// n! 값을 재귀적으로 구함
public static int factorial(int n)
{
if(n==0)
{
return 1;
}
return n * factorial(n-1);
}
// n! 값을 구함
@Test
void factorialTest() {
System.out.println("factorial Test");
System.out.println(Main.factorial(5));
}
120
순환함수와 수학적귀납법
- 정리
- factorial(int n)은 음이 아닌 정수 n에 대해서 n!을 올바르게 계산한다.
- 증명
- n=0인 경우: 1을 반환한다. 올바르다.
- 임의의 양의 정수 k에 대해서 n<k인 경우 n!을 올바르게 계산한다고 가정하자.
- n=k인 경우를 고려해보자. factorial은 먼저 factorial(k-1)을 호출하는데 2번의 가정에 의해서 (k-1)!이 올바르게 계산되어 반환된다. 따라서 메서드 factorial은 k*(k-1)!=k!을 반환한다.
Xⁿ
- x^0=1
- x^n=x∗x^(n-1) if n>0
// x^n 값을 재귀적으로 구함
public static double power(double x, int n)
{
if(n==0)
{
return 1;
}
return x * power(x,n-1);
}
// x^n 값을 구함
@Test
void powerTest() {
System.out.println("powerTest");
System.out.println(Main.power(2, 5));
}
32
Fibonacci Number
Fibonacci numbers는 제 0항을 0, 제 1항을 1로 두고 두번째 항부터는 바로 앞의 두수를 더한 수열입니다.
0 1 1 2 3 5 8 13 ...
- f_0 = 0
- f_1 = 1
- f_n = f_n-1 + f_n-2, n>1
// n번째의 피보나치 수를 구함
public static int fibo(int n)
{
if(n<2)
{
return n;
}
return fibo(n-1) + fibo(n-2);
}
// n번째 피보나치 수를 구함
@Test
void fibonaciTest() {
System.out.println("fibonaci Test");
System.out.println(Main.fibo(6));
}
8
최대공약수: Euclid Method
- m>=n인 두 양의 정수 m과 n에 대해서 m이 n의 배수이면 gcd(m,n)=n이다.
- m이 n의 배수가 아니면 gcd(m,n)=gcd(n,m%n)이다.
public static double gcd1(int m, int n)
{
if(m<n)
{
int tmp = m;
m = n;
n = tmp;
}
if(m%n==0)
{
return n;
}
else
{
return gcd(n, m%n);
}
}
@Test
void gcd1Test() {
System.out.println("gcd1 Test");
System.out.println(Main.gcd1(6, 3));
}
3.0
Euclid Method : 좀 더 단순한 버전
- gcd(p,q)
- if q=0 then p
- otherwise gcd(q, p%q)
// p, q의 최대 공약수를 구함
public static int gcd(int p, int q)
{
if(q==0)
{
return p;
}
return gcd(q, p%q);
}
// p, q의 최대공약수를 구함
@Test
void gcdTest() {
System.out.println("gcd Test");
System.out.println(Main.gcd(2, 3));
}
1
References
source code : https://github.com/yonghwankim-dev/inflearn_algorithm
[인프런] 영리한 프로그래밍을 위한 알고리즘 강좌
'Algorithm' 카테고리의 다른 글
[알고리즘][Recursion] 멱집합(Power Set) (0) | 2022.01.17 |
---|---|
[알고리즘][Recursion] Counting Cells in a Blob (0) | 2022.01.07 |
[알고리즘][Recursion] 미로찾기(Maze) (0) | 2021.12.24 |
[알고리즘][Recursion] 재귀(Recursion) 기본 개념과 예제 3 (0) | 2021.12.21 |
[알고리즘][Recursion] 재귀(Recursion) 기본 개념과 예제 2 (0) | 2021.12.21 |