
⇒ 재귀 알고리즘은 문제를 해결하기 위해 재귀 함수를 사용하는 알고리즘을 의미합니다
💡 팩토리얼 이란?
코드
public class Main {
public static void main(String[] args) {
System.out.println(factorial(5)); // 5! = 5 * 4 * 3 * 2 * 1 = 120
}
public static int factorial(int n) {
if (n == 0) { // 기본 케이스
return 1;
} else { // 재귀 케이스
return n * factorial(n - 1);
}
}
}
코드
public class Main {
public static void main(String[] args) {
System.out.println(sumNaturalNumber(5)); // 15
}
public static int sumNaturalNumber(int n) {
if (n == 1) {
return 1;
} else {
return n + sumNaturalNumber(n - 1);
}
}
}
💡 거듭제곱(pow)이란?
코드
public class Main {
public static void main(String[] args) {
System.out.println(power(2, 5)); // 15
}
public static int power(int base, int exponent) {
if (exponent == 0) {
return 1;
} else {
return base * power(base, exponent - 1);
}
}
}
💡reverseString() 함수를 통해 문자열의 값이 O가 되면 문자열을 반환하고 그렇지 않으면 첫번째 문자를 마지막 문자와 바꾸고 나머지 문자열에 대해 reverseString() 함수를 재귀적으로 호출한 결과를 반환합니다.
코드
public class Main {
public static void main(String[] args) {
System.out.println(reverseString("hello")); // "olleh"
}
public static String reverseString(String str) {
if (str.length() == 0) {// Base Case: 문자열 길이가 0이면 그대로 반환
return str;
} else {
return reverseString(str.substring(1)) + str.charAt(0);
}
}
}
str.substring(1)은 문자열의 첫 번째 문자를 제외한 나머지 부분을 반환합니다.reverseString(str.substring(1))은 나머지 부분을 뒤집습니다.str.charAt(0))를 덧붙입니다.💡 피보나치 수열이란?
코드
public static int fibonacci(int n) {
if (n == 0) {
return 0; // Base Case 1: n이 0이면 0 반환
} else if (n == 1) {
return 1; // Base Case 2: n이 1이면 1 반환
} else {
return fibonacci(n-1) + fibonacci(n-2); // Recursive Case: 이전 두 항의 합
}
}
n이 0이면 0을 반환, n이 1이면 1을 반환합니다.fibonacci(n-1)과 fibonacci(n-2)를 호출하여 두 값을 더한 결과를 반환합니다.코드(메모이제이션 적용 코드)
public class Main {
private static int[] memo;
public static void main(String[] args) {
int n = 5;
memo = new int[n + 1]; //크기가 n+1인 배열 memo 생성
System.out.println(fibonacci(n)); // 5
}
public static int fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (memo[n] != 0) return memo[n]; // 이미 계산된 값 반환
memo[n] = fibonacci(n - 1) + fibonacci(n - 2); // 계산 후 저장
return memo[n];
}
}
기본 재귀 함수는 중복된 계산이 많습니다. 예를 들어, fibonacci(5)를 계산할 때:
fibonacci(4)와 fibonacci(3)을 계산합니다.fibonacci(4)는 다시 fibonacci(3)과 fibonacci(2)를 계산합니다.fibonacci(3)는 또 fibonacci(2)와 fibonacci(1)을 계산합니다.결과적으로 같은 값(fibonacci(3) 등)을 여러 번 계산하게 됩니다. 이러한 중복 호출 때문에 시간 복잡도가 O(2^n)로 매우 비효율적입니다.
메모이제이션은 이미 계산한 값을 저장하여 중복 계산을 방지합니다.
memo) 준비:n + 1인 배열 memo를 생성합니다.memo[5]에는 fibonacci(5)의 값이 저장됩니다.memo[n]에 저장합니다.memo 배열에 저장되므로, 동일한 값에 대해 재계산하지 않습니다.fibonacci(3)은 처음 계산 후 memo[3]에 저장되며, 이후 호출 시 바로 반환합니다.fibonacci(n)은 최대 한 번만 계산됩니다.memo[n])은 O(1)의 시간 복잡도를 가집니다.memo 배열을 저장하기 위한 O(n)의 추가 공간이 필요합니다.💡 유클리드 호제법/알고리즘이란?
m = 48, n = 18일 때, 공약수는 1, 2, 3, 6이며, 최대공약수는 6입니다.코드
public static int gcd(int m, int n) {
if (n == 0) {
return m;
} else {
return gcd(n, m % n);
}
}
m과 n의 최대공약수는 n과 m % n의 최대공약수와 같습니다.gcd(48, 18) = gcd(18, 48 % 18) = gcd(18, 12)알고리즘의 단계
r = m % n을 계산합니다.gcd(n, r)을 재귀적으로 호출합니다.n == 0이 되면, m이 최대공약수입니다.💡 이진 탐색(Binary Search) 알고리즘이란?
low와 끝점 high를 설정합니다.mid를 계산합니다. (low+high)//2코드
public class BinarySearch {
public static int binarySearch(int[] arr, int target) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2; // 중간 인덱스 계산
if (arr[mid] == target) {
return mid; // 값을 찾음
} else if (arr[mid] < target) {
low = mid + 1; // 오른쪽 절반 탐색
} else {
high = mid - 1; // 왼쪽 절반 탐색
}
}
return -1; // 값이 없는 경우
}
public static void main(String[] args) {
int[] arr = {2, 4, 7, 10, 14, 18, 21};
int target = 14;
int result = binarySearch(arr, target);
if (result != -1) {
System.out.println("값 " + target + "는 인덱스 " + result + "에 있습니다.");
} else {
System.out.println("값 " + target + "는 배열에 없습니다.");
}
}
}
💡 이항계수(binomial theorem) 알고리즘이란?
코드
public static int binomialCoefficient(int n, int k) {
if (k == 0 || k == n) {
return 1;
} else {
return binomialCoefficient(n-1, k-1) + binomialCoefficient(n-1, k);
}
}

오늘은 재귀 알고리즘에 대해 공부를 해보았습니다. 다음에는 백트래킹 알로리즘에 대한 글로 찾아뵙겠습니다!