Résolution de problèmes avec la programmation dynamique

Approches de programmation dynamique

Suite de Fibonacci - Approche descendante

Le problème de Fibonacci (LeetCode 509) peut être résolu avec deux approches descendantes : la récursion complète et la récursion avec mémorisation.

public int fibonacci(int n) {
    int[] cache = new int[n + 1];
    return calculerFibonacci(cache, n);
}

private int calculerFibonacci(int[] cache, int n) {
    if (n <= 1) {
        return n;
    }
    if (cache[n] != 0) {
        return cache[n];
    }
    cache[n] = calculerFibonacci(cache, n - 1) + calculerFibonacci(cache, n - 2);
    return cache[n];
}

Suite de Fibonacci - Approche asecndante

L'approche ascendante élimine la récursion en construisant la solution progressivement.

public int fibonacciIteratif(int n) {
    if (n <= 1) {
        return n;
    }
    int precedent1 = 0;
    int precedent2 = 1;
    int resultat = 0;
    
    for (int i = 2; i <= n; i++) {
        resultat = precedent1 + precedent2;
        precedent1 = precedent2;
        precedent2 = resultat;
    }
    return resultat;
}

Échange de monnaie - Approche récursive

Le problème d'échange de monnaie (LeetCode 322) consiste à trouver le nombre minimum de pièces pour former un montant donné.

private int[] memoire;

public int nombreMinimumPieces(int[] pieces, int montant) {
    memoire = new int[montant + 1];
    Arrays.fill(memoire, -999);
    return resoudreSousProbleme(pieces, montant);
}

private int resoudreSousProbleme(int[] pieces, int reste) {
    if (reste == 0) return 0;
    if (reste < 0) return -1;
    
    if (memoire[reste] != -999) {
        return memoire[reste];
    }
    
    int minimum = Integer.MAX_VALUE;
    for (int piece : pieces) {
        int sousResultat = resoudreSousProbleme(pieces, reste - piece);
        if (sousResultat == -1) continue;
        minimum = Math.min(minimum, sousResultat + 1);
    }
    
    memoire[reste] = (minimum != Integer.MAX_VALUE) ? minimum : -1;
    return memoire[reste];
}

Échange de monnaie - Programmation dynamique

L'approche itérative construit la solution du plus petit montant vers le montant cible.

public int echangeMonnaieDP(int[] pieces, int montant) {
    int[] dp = new int[montant + 1];
    Arrays.fill(dp, montant + 1);
    dp[0] = 0;
    
    for (int i = 1; i <= montant; i++) {
        for (int piece : pieces) {
            if (i - piece >= 0) {
                dp[i] = Math.min(dp[i], dp[i - piece] + 1);
            }
        }
    }
    
    return dp[montant] <= montant ? dp[montant] : -1;
}

Étiquettes: Programmation-Dynamique Fibonacci échange-monnaie récursion mémorisation

Publié le 10 septembre à 18h16