public void recursion() {
System.out.println("This is");
System.out.println("recursion!");
recursion();
}
recursion
메서드처럼 자기 자신을 호출하는 함수를 재귀 함수라고 함
문제 해결하기
문제: 자연수로 이루어진 리스트(배열)를 입력받고, 리스트의 합을 리턴한는 메서드 'arrSum'을 작성하세요.
자연수로 이루어진 리스트(배열)의 합을 구하는 알고리즘
sum
을 0
으로 초기화한다.sum
에 더한다.public int arrSum(int[] arr) {
int sum = 0;
for(int i=0; i < arr.length; i++){
sum += arr[i];
}
return sum;
}
재귀로 문제를 해결하는 방법
1. 문제를 좀 더 작게 쪼개기
2. 1번과 같은 방식으로 문제가 더는 작아지지 않을 때까지 가장 작은 단위로 문제르 쪼갬
3. 가장 작은 단위의 문제를 해결함으로써 전체 문제를 해결함
arrSum([1, 2, 3, 4, 5]) == 1 + arrSum([2, 3, 4, 5])
arrSum([2, 3, 4, 5]) == 2 + arrSum([3, 4, 5])
...
...
arrSum([3, 4, 5]) == 3 + arrSum([4, 5])
arrSum([4, 5]) == 4 + arrSum([5])
arrSum([5]) == 5 + arrSum([])
arrSum([]) == 0; // <-- 문제가 더는 작아지지 않는 순간
// 가장 작은 경우의 해결책을 적용함
arrSum([5]) = 5 + arrSum([]) == 5 + 0 == 5;
arrSum([4, 5]) == 4 + arrSum([5]) == 4 + 5 == 9;
arrSum([3, 4, 5]) == 3 + arrSum([4, 5]) == 3 + 9 == 12;
arrSum([2, 3, 4, 5]) == 2 + arrSum([3, 4, 5]) == 2 + 12 == 14;
arrSum([1, 2, 3, 4, 5]) == 1 + arrSum([2, 3, 4, 5]) == 1 + 14 == 15;
arrSum
메서드의 리턴값이 나오면서 연쇄적으로 문제가 해결되고, 최종적으로 문제 전체가 해결됨
public int arrSum(int[] arr) {
// 빈 배열을 받았을 때 0을 리턴하는 조건문
// --> 가장 작은 문제를 해결하는 코드 & 재귀를 멈추는 코드
if (arr.length == 0) {
return 0;
}
int[] tail = Arrays.copyOfRange(arr, 1, arr.length);
// 배열의 첫 요소 + 나머지 요소가 담긴 배열을 받는 arrSum 함수
// --> 재귀(자기 자신을 호출)를 통해 문제를 작게 쪼개나가는 코드
return arr[0] + arrSum(tail);
}
arrSum 메서드가 내부에서 arrSum 메서드를 호출하면서 문제가 쪼개어져 나가고 결국은 더 이상 쪼갤 수 없는 arrSum([]) 까지 메서드가 호출됨.
arrSum([])
는 조건문에 의해 더 이상 자기 자신을 호출하지 않고 숫자 0을 리턴하면서 종료됨. 그 결과 중첩되어있던 메서드들도 연쇄적으로 숫자를 리턴하고 최종적으로는 배열의 모든 요소의 합을 리턴함녀서 문제가 해결됨.