πŸ’» Computer Science/- Data Structure, Algorithm

[μ•Œκ³ λ¦¬μ¦˜-λ°±μ€€(DP)] λ°±μ€€ 2748(DP), 10870(Recursive) ν”Όλ³΄λ‚˜μΉ˜μ˜ 수 차이

Wonit 2020. 3. 1. 02:02

이번 ν¬μŠ€νŒ…μ—μ„œ 동적 ν”„λ‘œκ·Έλž˜λ°(DP, 동적 κ³„νšλ²•, λ©”λͺ¨μ΄μ œμ΄μ…˜ 풀이) 에 λŒ€ν•œ κ°„λ‹¨ν•œ μ •μ˜μ™€ 문제 풀이λ₯Ό ν•΄λ³Ό 것이닀

동적 κ³„νšλ²•μ— λŒ€ν•œ κΉŠμ€ 이해와 이둠적 μ„€λͺ…은 좔후에 μ•Œκ³ λ¦¬μ¦˜ 이둠 μ—μ„œ λ‹€λ£¨κΈ°λ‘œ ν•˜κ² λ‹€.

 

동적 κ³„νšλ²•μ΄λž€?

 

ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ 동적 κ³„νšλ²•μ— ν‘œν˜„μ„ ν•˜κ³€ ν•œλ‹€.

 

동적 ν”„λ‘œκ·Έλž˜λ°μ€ 큰 문제λ₯Ό μž‘μ€ 문제둜 λ‚˜λˆ„μ–΄ ν•΄κ²°ν•˜λ €λŠ” 문재 ν•΄κ²° μ „λž΅μ΄λ‹€.

 

μ΄λŠ” λΆ„ν•  정볡과 νŠΉμ • 문제의 μž¬κ·€ 호좜 λΉ„μŠ·ν•œ κ°œλ…μ΄μ§€λ§Œ κ°€μž₯ 큰 차이점은 λ©”λͺ¨μ΄μ œμ΄μ…˜(Memoization) 을 ν•˜λŠλƒ μ•ˆ ν•˜λŠλƒμ— 따라 달렸닀고 ν•œλ‹€.

Memoization

 

λ©”λͺ¨μ œμ΄μ…˜μ΄λž€, DPμ—μ„œ μž‘μ€ λ¬Έμ œλ“€μ΄ 해결될 λ•Œ ν•΄λ‹Ή κ²°κ³Όλ₯Ό μ €μž₯ν•˜μ—¬ λ‹€λ₯Έ λΆ€λΆ„μ˜ λ™μΌν•œ 계산에, μ €μž₯된 κ²°κ³Όλ₯Ό μ‚¬μš©ν•˜λŠ” 것을 λœ»ν•œλ‹€.


λ©”λͺ¨μ΄μ œμ΄μ…˜μ„ 효과적으둜 μ„€λͺ…ν•˜κΈ° μœ„ν•΄μ„œλŠ” ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ μ΄μš©ν•œ DPκ°€ κ°€μž₯ 효율적인데 ν•œ 번 λ°”λ‘œ ν™•μΈν•΄λ³΄μž.

 

λ°±μ€€ 10870번 : μž¬κ·€ν˜ΈμΆœ

 

λ°±μ€€ 문제 10870 은 μž¬κ·€ν˜ΈμΆœμ„ μ΄μš©ν•΄μ„œ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ μ™„μ„±μ‹œν‚€λŠ” 것이 λͺ©μ μΈλ° μ•„λž˜μ˜ μž…λ ₯을 잘 봐보자.

n이 20보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜λ‘œ μ œν•œλ˜μ–΄ μžˆλŠ”λ° μˆ˜ν–‰ μ‹œκ°„μ€ 1μ΄ˆμ΄λ‹€.

 

package stage.stage09_Recursive;

import java.util.Scanner;

public class Prob02_FibonacciNumvbers {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        int num = input.nextInt();

        System.out.println(fibonacci(num));

    }

    private static int fibonacci(int num){

        if(num >= 2) return fibonacci(num - 1) + fibonacci(num - 2);

        else return num;

    }
}

 

μœ„μ™€ 같은 μ½”λ“œλ‘œ ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό μž¬κ·€ν˜ΈμΆœ ν•œλ‹€λ©΄ μ‹œκ°„ λ³΅μž‘λ„λŠ” 2^n 이 될 것이닀. ν•˜μ§€λ§Œ λ¬Έμ œμ—μ„œ 봀듯이 n이 20보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜λ₯Ό 이 μ‹œκ°„ λ³΅μž‘λ„μ— μ μš©ν•œλ‹€λ©΄

 

 

100만이 쑰금 λ„˜λŠ” 수둜 1μ΄ˆμ— 1μ–΅λ²ˆ 계산을 ν•œλ‹€λŠ” κ°€μ •ν•˜μ— μΆ©λΆ„νžˆ ν”Όλ³΄λ‚˜μΉ˜λ₯Ό μž¬κ·€ 호좜둜써 해결해도 λœλ‹€λŠ” μ†Œλ¦¬λ‹€

 

ν•˜μ§€λ§Œ n이 컀진닀면 μ–΄λ–»κ²Œ 될까?

 

μ΄λŸ¬ν•œ λ¬ΌμŒμ—μ„œ 동적 ν”„λ‘œκ·Έλž˜λ°μ΄ μ‹œμž‘ν•œλ‹€.

 

동적 ν”„λ‘œκ·Έλž˜λ°μ€ μ•„κΉŒ μœ„μ—μ„œ 말 ν–ˆλ“― λ©”λͺ¨μ œμ΄μ…˜μœΌλ‘œ λ©”λͺ¨λ¦¬μ˜ λ‚­λΉ„λ₯Ό 쀄인닀고 ν–ˆλŠ”λ° μœ„μ™€ 같은 λ°©μ‹μ˜ μž¬κ·€ 호좜이 μ‹¬κ°ν•œ λ©”λͺ¨λ¦¬μ˜ λ‚­λΉ„κ°€ μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

 

private static int fibonacci(int num){
    if(num >= 2) return fibonacci(num - 1) + fibonacci(num - 2);
    else return num;
}

 

λ§Œμ•½ n 6이면

 

 

이런 μ‹μœΌλ‘œ 쀑볡이 계속 λˆ„μ λ˜κ³  κ²°κ΅­ ν•„μš”μ—†λŠ” λ©”λͺ¨λ¦¬μ˜ λ‚­λΉ„κ°€ μ‘΄μž¬ν•œλ‹€. λ°±μ€€μ˜ 2748번과 같이 n이 90κΉŒμ§€ ν—ˆμš©λœλ‹€λ©΄ λ‹€μŒκ³Ό 같은 동적 ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ ν•΄κ²°ν•΄μ•Ό λ°”λžŒμ§ν•˜λ‹€.

 

λ°±μ€€ 2748번 : 동적 κ³„νšλ²•

 

 

이에 λŒ€ν•œ μ½”λ“œλ₯Ό 동적 ν”„λ‘œκ·Έλž˜λ°μ˜ λ©”λͺ¨μ œμ΄μ…˜μ„ μ΄μš©ν•˜μ—¬ ν’€μ–΄λ³΄μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€. (μ½”λ“œλ₯Ό μœ μ‹¬ν•˜κ²Œ 보길 λ°”λž€λ‹€)

 

package stage.stage09_Recursive;

import java.util.Scanner;

public class Prob03_Fibonacci2 {

    static long[] memo;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        memo = new long[91]; // κΈ°μ–΅ν•  곡간이 n λ§ŒνΌμ΄λ―€λ‘œ n+1을 ν• λ‹Ή

        int n = input.nextInt();

        System.out.println(fibonacci(n));
    }

    private static long fibonacci(int n){

        if(n <= 1)  return n; //fibonacci(0) 와 fibonacci(1)은 각각 0κ³Ό 1이 λ―€λ‘œ λ°”λ‘œ return

        else { // κ·Έλ ‡μ§€ μ•Šμ„ 경우

            if(memo[n] > 0) return memo[n]; //λ©”λͺ¨μ— 값이 μ €μž₯된 경우

            else memo[n] = fibonacci(n - 1) + fibonacci(n - 2); // 값이 μ €μž₯λ˜μ§€ μ•Šμ€ 경우

            return memo[n];
        }
    }
}

 

μœ„μ™€ 같이 static ν•„λ“œλ‘œ memoλΌλŠ” 배열에 값을 λ‹΄κ³  ν•œ 번 fibonacci() λ©”μ„œλ“œκ°€ μˆ˜ν–‰λ˜λ©΄ memo에 값을 λ¨Όμ € κ²€μ‚¬ν•œ λ’€ memo에 λŒ€ν•œ κ²°κ³Όκ°€ 없을 λ•Œλ§Œ μž¬κ·€μ μœΌλ‘œ ν˜ΈμΆœν•˜λŠ” 방식을 λ°”λ‘œ DP적 풀이라고 ν•œλ‹€.