코드


class Main {
	
	static int stackFrame(int n){
		if(n<=2) return 1;
		else return stackFrame(n-2)	+stackFrame(n-1);
	}
	
	
	public static void main(String[] args){
		int n=10;
		
		long start = System.nanoTime();
		for(int i=1; i<=n; i++) System.out.print(Main.stackFrame(i)+" ");
		System.out.println();
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		
		start = System.nanoTime();
		int[] intArr = useArray(n);
		System.out.println(Arrays.toString(intArr));
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		
	}

	private static int[] useArray(int n) {
		int[] intArr = new int[n];
		for(int i=1; i<=n; i++) {
			if(i<=2) {
				intArr[i-1] = 1;
			} else {
				intArr[i-1] = intArr[i-2]+intArr[i-3];
			}
		}
		return intArr;
	}	
}

결과

1 1 2 3 5 8 13 21 34 55 
총 소요 시간 : 242100
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
총 소요 시간 : 48000

 


단순 재귀 호출로는 값이 클 수록 매번 이전 값을 계산하느라 시간 소요가 기하급수적으로 증가한다.

반면에 배열은 이전 값을 재귀적으로 구하지 않으니 값 계산 속도는 선형적으로 증가한다.

import java.util.Arrays;

class Main {
	static int cnt = 0;
	
	static int stackFrame(int n){
		cnt++;
		if(n<=2) return 1;
		else return stackFrame(n-2)	+stackFrame(n-1);
	}
	
	
	public static void main(String[] args){
		int n=45;
		
		long start = System.nanoTime();
		for(int i=1; i<=n; i++) System.out.print(Main.stackFrame(i)+" ");
		System.out.println();
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		System.out.println("총 호출 수 : "+cnt);
		
		cnt=0;
		start = System.nanoTime();
		int[] intArr = useArray(n);
		System.out.println(Arrays.toString(intArr));
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		System.out.println("총 반복 수 : "+cnt);
		
	}

	private static int[] useArray(int n) {
		int[] intArr = new int[n];
		for(int i=1; i<=n; i++) {
			cnt++;
			if(i<=2) {
				intArr[i-1] = 1;
			} else {
				intArr[i-1] = intArr[i-2]+intArr[i-3];
			}
		}
		return intArr;
	}	
}

몇 번 호출되는지 카운트 해봤다.

 

 

재귀 호출로 매 번 계산은 비효율적이니 상태값을 저장할 배열을 생성해 적용해보자

import java.util.Arrays;

class Main {
	static int cnt = 0;
	static int[] stackArr;
	
	static int stackFrame(int n){
		cnt++;
		if(n<=2) return 1;
		else return stackFrame(n-2)	+stackFrame(n-1);
	}
	
	static int stackFramePlusArray(int n){
		cnt++;
		if(stackArr[n]>0) return stackArr[n];
		if(n<=2) return stackArr[n]=1;
		else return stackArr[n]=stackFramePlusArray(n-2)+stackFramePlusArray(n-1);
	}
	
	private static int[] useArray(int n) {
		int[] intArr = new int[n];
		for(int i=1; i<=n; i++) {
			cnt++;
			if(i<=2) {
				intArr[i-1] = 1;
			} else {
				intArr[i-1] = intArr[i-2]+intArr[i-3];
			}
		}
		return intArr;
	}	
	
	public static void main(String[] args){
		int n=45;
		
		long start = System.nanoTime();
		for(int i=1; i<=n; i++) System.out.print(Main.stackFrame(i)+" ");
		System.out.println("\n반복문 + 재귀");
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		System.out.println("총 호출 수 : "+cnt);
		
		cnt=0;
		stackArr = new int[n+1];//인덱스 0자리 쓰기 싫어서 +1
		start = System.nanoTime();
		System.out.println("######################################");
		for(int i=1; i<=n; i++) System.out.print(Main.stackFramePlusArray(i)+" ");
		System.out.println("\n반복문 + 재귀(메모이제이션)");
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		System.out.println("총 호출 수 : "+cnt);
		
		cnt=0;
		Arrays.fill(stackArr, 0);
		start = System.nanoTime();
		Main.stackFramePlusArray(n);
		System.out.println("######################################");
		System.out.print(Arrays.toString(stackArr));
		System.out.println("\n재귀(메모이제이션)");
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		System.out.println("총 호출 수 : "+cnt);
		
		
		cnt=0;
		start = System.nanoTime();
		int[] intArr = useArray(n);
		System.out.println("######################################");
		System.out.println(Arrays.toString(intArr));
		System.out.println("반복문");
		System.out.println("총 소요 시간 : " + (System.nanoTime()-start));
		System.out.println("총 반복 수 : "+cnt);
		
	}

}

배열에 미리 계산된 값이 있다면, 더 이상 계산할 것 없이 그 값을 반환하도록 했다.

 

 

 

 

 

코드

class Main {
	public int DFS(int n){
		if(n==1) {
			System.out.print(1 + " = ");
			return 1;
		} else {
			System.out.print(n + " * ");
			return n*DFS(n-1);
		}
	}
	public static void main(String[] args){
		Main T = new Main();
		System.out.println(T.DFS(10));
		int sum = 1;
		for (int i = 1; i <= 10; i++) {
			sum *= i;
			if(i==10) System.out.print(i+" = " + sum);
			else System.out.print(i + " * ");
		}
		
		
	}	
}

결과

10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 = 3628800

 

'자료구조&알고리즘 > 자바(Java) 알고리즘 문제풀이 : 코딩테스트 대비' 카테고리의 다른 글

이분검색  (0) 2023.02.16
피보나치 수열  (0) 2023.02.13
이진수 구하기(재귀)  (0) 2023.02.08
재귀함수  (0) 2023.02.05
뮤직비디오  (0) 2022.12.20

+ Recent posts