294 votes

Trouver toutes les combinaisons possibles de chiffres pour atteindre une somme donnée.

Comment faire pour tester toutes les combinaisons possibles d'ajouts à partir d'un ensemble donné. N de nombres pour qu'ils aboutissent à un nombre final donné ?

Un bref exemple :

  • Ensemble de chiffres à ajouter : N = {1,5,22,15,0,...}
  • Résultat souhaité : 12345

9 votes

L'article de wikipedia ( fr.wikipedia.org/wiki/Sous-ensemble_somme_problème ) mentionne même que ce problème est une bonne introduction à la classe des problèmes NP-complets.

6 votes

Peut-on utiliser plus d'une fois le même élément de l'ensemble original ? Par exemple, si l'entrée est {1,2,3,5} et la cible 10, est-ce que 5 + 5 = 10 est une solution acceptable ?

0 votes

Juste une fois. Si un nombre entier doit être répété, il apparaît comme un nouvel élément.

1voto

Prabodh Mhalgi Points 526

Je faisais quelque chose de similaire pour une affectation en scala. J'ai pensé à poster ma solution ici :

 def countChange(money: Int, coins: List[Int]): Int = {
      def getCount(money: Int, remainingCoins: List[Int]): Int = {
        if(money == 0 ) 1
        else if(money < 0 || remainingCoins.isEmpty) 0
        else
          getCount(money, remainingCoins.tail) +
            getCount(money - remainingCoins.head, remainingCoins)
      }
      if(money == 0 || coins.isEmpty) 0
      else getCount(money, coins)
    }

1voto

feihcsim Points 533

Recommandé comme réponse :

Voici une solution utilisant es2015 générateurs :

function* subsetSum(numbers, target, partial = [], partialSum = 0) {

  if(partialSum === target) yield partial

  if(partialSum >= target) return

  for(let i = 0; i < numbers.length; i++){
    const remaining = numbers.slice(i + 1)
        , n = numbers[i]

    yield* subsetSum(remaining, target, [...partial, n], partialSum + n)
  }

}

L'utilisation de générateurs peut en fait être très utile car elle vous permet de mettre en pause l'exécution du script immédiatement après avoir trouvé un sous-ensemble valide. Ceci est en contraste avec les solutions sans générateurs (c'est-à-dire sans état) qui doivent itérer à travers chaque sous-ensemble unique de numbers

1voto

Luillyfe Jade Points 33

Je n'ai pas aimé la solution Javascript que j'ai vue ci-dessus. Voici celle que j'ai construite en utilisant l'application partielle, les fermetures et la récursion :

Ok, je m'inquiétais surtout de savoir si le tableau des combinaisons pouvait satisfaire aux exigences de l'objectif. J'espère que cette approche vous permettra de trouver les autres combinaisons.

Ici, il suffit de définir la cible et de passer le tableau des combinaisons.

function main() {
    const target = 10
    const getPermutationThatSumT = setTarget(target)
    const permutation = getPermutationThatSumT([1, 4, 2, 5, 6, 7])

    console.log( permutation );
}

l'implémentation actuelle que j'ai trouvée

function setTarget(target) {
    let partial = [];

    return function permute(input) {
        let i, removed;
        for (i = 0; i < input.length; i++) {
            removed = input.splice(i, 1)[0];
            partial.push(removed);

            const sum = partial.reduce((a, b) => a + b)
            if (sum === target) return partial.slice()
            if (sum < target) permute(input)

            input.splice(i, 0, removed);
            partial.pop();
        }
        return null
    };
}

0voto

Dheerendra Dev Points 64
function solve(n){
    let DP = [];

     DP[0] = DP[1] = DP[2] = 1;
     DP[3] = 2;

    for (let i = 4; i <= n; i++) {
      DP[i] = DP[i-1] + DP[i-3] + DP[i-4];
    }
    return DP[n]
}

console.log(solve(5))

Il s'agit d'une solution dynamique pour JS qui indique le nombre de façons dont chacun peut obtenir une certaine somme. Cela peut être la bonne solution si vous pensez à la complexité en temps et en espace.

0voto

Neelesh Salpe Points 161
import java.util.*;

public class Main{

     int recursionDepth = 0;
     private int[][] memo;

     public static void main(String []args){
         int[] nums = new int[] {5,2,4,3,1};
         int N = nums.length;
         Main main =  new Main();
         main.memo = new int[N+1][N+1];
         main._findCombo(0, N-1,nums, 8, 0, new LinkedList() );
         System.out.println(main.recursionDepth);
     }

       private void _findCombo(
           int from,
           int to,
           int[] nums,
           int targetSum,
           int currentSum,
           LinkedList<Integer> list){

            if(memo[from][to] != 0) {
                currentSum = currentSum + memo[from][to];
            }

            if(currentSum > targetSum) {
                return;
            }

            if(currentSum ==  targetSum) {
                System.out.println("Found - " +list);
                return;
            }

            recursionDepth++;

           for(int i= from ; i <= to; i++){
               list.add(nums[i]);
               memo[from][i] = currentSum + nums[i];
               _findCombo(i+1, to,nums, targetSum, memo[from][i], list);
                list.removeLast();
           }

     }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X