Algorithm | 재귀 함수(Recursion Function)
재귀 함수
재귀 함수는 프로세서 처리 중에 자신을 호출하는 것을 다시 호출하는 함수를 말한다.
예를 들어, 1에서 N까지의 합을 구하는 함수는 재귀를 사용하여 다음과 같이 정의할 수 있다.
public class SumRecursion {
public int sum(int n) {
if(n == 0) {
return 0;
}
return n + sum(n - 1);
}
public static void main(String[] args) {
SumRecursion recursion = new SumRecursion();
int result = recursion.sum(10);
System.out.println(result); // 55
}
}
실행 결과:
55
주의할 점은 sum(10)
를 호출하고 있지만, 처음에 값을 반환 되는 값은 sum(0)
이다. 그리고 마지막으로 sum(10)
값을 반환하게 된다.
유클리드 호제법
유클리드 호제법은 두 개의 정수 m, n의 최대 공약수(GCD(m, n)를 찾는 알고리즘이다.
m을 n으로 나누었을 때. 나머지를 r이라고 하면, 아래와 같이 정의된다.
GCD(m, n) = GCD(n, r)
재귀 함수를 사용하면 수학으로 유명한 유클리드 호제법 알고리즘을 작성할 수 있다.
public class GcdRecursion {
public int gcd(int m, int n) {
if(n == 0) {
return m;
}
return gcd(n, m % n);
}
public static void main(String[] args) {
GcdRecursion recursion = new GcdRecursion();
int result = recursion.gcd(30, 7);
System.out.println(result); // 1
}
}
실행 결과:
1
피보나치 수열
피보나치 수열의 알고리즘은 재귀를 두번 사용하여 만들 수 있고, 아래와 같이 정의된다.
F0 = 0
F1 = 1
Fn = Fn-1 + Fn-2 (n = 2, 3, ...)
public class FibonacciRecursion {
public int fibonacci(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String[] args) {
FibonacciRecursion recursion = new FibonacciRecursion();
int result = recursion.fibonacci(10);
System.out.println(result); // 55
}
}
실행 결과:
55
이제 작성한 피보나치 수열의 알고리즘 복잡도는 O((1+√5)^n/2)
이다.
a에서 b의 합계를 구하기
아래 코드는 a에서 b의 합계를 구하는 예제이다.
package com.devkuma.algorithum.programming.recursion;
public class SumRangeRecursion {
int sumRange(int a, int b) {
if (a == b) {
return a;
}
return sumRange(a, b - 1) + b;
}
public static void main(String[] args) {
SumRangeRecursion recursion = new SumRangeRecursion();
int result = recursion.sumRange(1, 3);
System.out.println(result); // 6
}
}
실행 결과:
6
위에 예제에서는 1 + 2 + 3 + 4 + 5 = 15
와 같이 계산된다.
이를 풀어 쓰면 아래와 같다.
sumRange(1, 5) = sumRange(1, 5 - 1) + 5 > sumRange(1, 4) + 5 > 10 + 5 = 15
sumRange(1, 4) = sumRange(1, 4 - 1) + 4 > sumRange(1, 3) + 4 > 6 + 4 = 10
sumRange(1, 3) = sumRange(1, 3 - 1) + 3 > sumRange(1, 2) + 3 > 3 + 3 = 6
sumRange(1, 2) = sumRange(1, 2 - 1) + 2 > sumRange(1, 1) + 2 > 1 + 2 = 3
sumRange(1, 1) = 1
소수인지 여부 판단
아래 코드는 소수인지 여부를 판단하는 예제이다.
public class PrimeRecursion {
boolean hasDivisor(int n, int i) {
if (i == n) {
return false;
}
if (n % i == 0) {
return true;
}
return hasDivisor(n, i + 1);
}
boolean isPrime(int n) {
if (n == 1) {
return false;
} else if (n == 2) {
return true;
} else {
return !hasDivisor(n, 2);
}
}
public static void main(String[] args) {
PrimeRecursion recursion = new PrimeRecursion();
boolean result1 = recursion.isPrime(7);
System.out.println(result1); // true
boolean result2 = recursion.isPrime(4);
System.out.println(result2); // false
}
}
실행 결과:
true
false
상호 재귀: 홀수 짝수 판단
아래 코드는 홀수 짝수를 판단하는 예제로써 메소드가 서로 호출하는 상호 재귀 함수으로 구현되었다.
package com.devkuma.algorithum.programming.recursion;
public class EvenOddRecursion {
boolean isEven(int n) {
if (n == 0) {
return true;
}
return isOdd(n-1);
}
boolean isOdd(int n) {
if (n == 0) {
return false;
}
return isEven(n-1);
}
public static void main(String[] args) {
EvenOddRecursion recursion = new EvenOddRecursion();
System.out.println(recursion.isEven(8)); // true
System.out.println(recursion.isEven(9)); // false
System.out.println(recursion.isOdd(8)); // false
System.out.println(recursion.isOdd(9)); // true
}
}
실행 결과:
true
false
false
true
배열에서 최대값 구하기
아래 코드는 입력 받은 배열 a에서 개수가 n까지의 최대값을 구하는 예제이다.
public class MaxArrayRecursion {
public static int max(int[] a, int n) {
int x;
if (n == 1) {
return a[0];
} else {
x = max(a, n - 1);
}
if (x > a[n - 1]) {
return x;
}
return a[n - 1];
}
public static void main(String[] args) {
int arr[] = {0, 80, 60, 40, 20, 100};
System.out.println(max(arr, 3));
}
}
실행 결과:
8
입력 받은 배열 a에서 3번째까지는 “0, 80, 60"이고, 여기서 제일 큰 값은 “80"이 된다.
최종 수정 : 2022-04-02