자바 팩토리얼 코드 재귀/메모이제이션 기법
팩토리얼
팩토리얼은 1 부터 자기 자신까지의 수의 곱을 의미한다. 연산 기호로는 숫자뒤에 !를 붙여서. 예외적으로 0! 와 1! 는 둘다 1을 의미한다. 3! = 6, 4! = 24
팩토리얼 코드 버전 1 - 재귀
재귀를 활용한다면 코드를 짧고 간결하게 팩토리얼 로직을 구현할 수 있다.
int n = 10
fact(n)
int fact(int n) {
if(n == 0 || n == 1){
return 1
} else {
return n * fact(n-1)
}
}
재귀로 표현하면 간결하고 쉽게 작성할 수 있지만 큰 단점이 존재한다. 수가 커졌을 경우 스택의 복귀 주소가 계속해서 쌓이다가 스택 오버플로우가 발생하여 코드가 멈춰버린다. 즉, 일정 숫자 이상의 크기는 재귀를 활용하여 팩토리얼 구현하는 것은 위험할 수 있다.
팩토리얼 코드 버전 2 - 메모이제이션
재귀의 방식이 편하지만 메모이제이션 기법을 활용하여 팩토리얼 코드를 구현할 수 있다.
int n = 10
int [] fact = new int[n + 1]
fact[0] = 1 ; fact[1] = 1
for(int i=1 ; i<=10 ; i++) {
fact[i] = i * fact[i-1]
}
배열을 활용하여 이전의 팩토리얼 계산을 저장함. fact[2] = 2 * fact[1]이고 fact[3] = 3 * fact[2] 이런식으로 저장된 값을 활용하기에 계속해서 활용할 수 있다. 숫자가 늘어나도 배열의 사이즈를 크게 또는 타입형만 바꿔주면 되므로 스택 오버플로우의 문제를 걱정할 필요가 없다.
int n = 10
int [] fact = new int[n + 1]
if(fact[n] == 0 ) factorial(fact)
print(fact[n])
factorial(int [] fact) {
fact[0] = 1 ; fact[1] = 1
for(int i=1 ; i<=10 ; i++) {
fact[i] = i * fact[i-1]
}
}
위의 코드를 함수로 작성하고 값이 있는지 확인하고 호출한다면 fact가 없는 값만 갱신을 하기 때문에 효율적으로 코드를 구현할 수 있음. fact[100] 을 한 번 구했었더라면 fact[1~99]까지의 팩토리얼 값은 계산할 필요없이 배열의 값만 출력하면 된다.
결론
- 메모이제이션 기법!!! 배열을 통해 이전의 연산을 저장하고 활용하기에 효율적임
- IT 면접/손코딩 때 팩토리얼 기법 활용 가능