Ce que je trouve le plus facile, c'est de traduire le problème d'une mot en un problème plus logique.
Commencer par un ensemble vide : [[]]
L'astuce consiste à créer un ensemble vide dans ce problème mais immédiatement vous montre un ensemble qui contient un élément.
Si nous décomposons cela en tableaux à la place (parce que je trouve personnellement que c'est plus intuitif), nous pouvons le traduire par :
Commencez par un tableau de tableaux, dont le premier élément est un tableau vide. (au lieu de null
)
En résumé
int[][] result = new int[]{ new int[0] };
Maintenant que nous avons un point de départ, nous pouvons commencer à traduire les autres parties du problème.
Ajoutez le premier numéro (1) à tous les sous-ensembles existants pour créer des sous-ensembles : [[],[1]]
Ajouter le deuxième chiffre (5) à tous les sous-ensembles existants ...
Ajouter le troisième chiffre (3) à tous les sous-ensembles existants ...
Il y a beaucoup d'informations ici. Traduisons-en les différentes parties
Ajouter le 1er numéro ...
Ajouter le 2e numéro ...
Ajouter le nième nombre ...
La répétition de ces instructions et le fait que chaque nombre 1, 5, 3
correspond à notre ensemble initial de {1, 5, 3}
nous indique que nous devrions utiliser un boucle d'une manière ou d'une autre pour construire notre résultat.
for(int i = 0; i < set.Length; i++)
{
int number = set[i];
// add subsets some how
}
Ajouter le numéro à tous les pour créer des sous-ensembles : [[],[1]
Quelques points méritent d'être soulignés. Remarquez qu'ils ont utilisé le mot Ajouter mais donnez un exemple où le numéro n'a pas été ajouté à l'un des sous-ensembles existants. [[]]
s'est transformé en [[],[1]]
. Pourquoi l'un d'entre eux reste-t-il vide si nous avons ajouté 1
à chacun d'entre eux ?
La raison en est que lorsque nous créons les nouveaux sous-ensembles et toutes leurs variations, nous voulons conserver les anciens. Ainsi, nous faire ajouter le 1
à []
(le premier élément) mais nous faisons un copie de []
d'abord. Ainsi, lorsque nous ajouterons 1
à cette copie, nous disposons toujours de l'original []
et maintenant un tout nouveau [1]
on peut alors combiner les créer [[],[1]]
.
Grâce à ces indices, nous pouvons déchiffrer que Ajouter le numéro à tous les sous-ensembles existants signifie en fait fait des copies de tous les sous-ensembles existants, ajoute le nombre à chacune des copies, puis ajoute ces copies à la fin du tableau de résultats .
int[][] result = new int[]{ new int[0] };
int[] copy = result[0];
copy.Append(1); // pseudo code
result.Append(copy); // pseudo code
// result: [[],[1]]
Rassemblons toutes ces pièces et trouvons la solution finale, du moins nous l'espérons !
Voici un exemple que j'ai mis au point et qui fonctionne (du moins selon les données de votre exemple).
object[] set = { 1, 5, 3 };
// [null]
object[][] result = Array.Empty<object[]>();
// add a [] to the [null] creating [[]]
Append(ref result, Array.Empty<object>());
// create a method so we can add things to the end of an array
void Append<T>(ref T[] array, T SubArrayToAdd)
{
int size = array.Length;
Array.Resize(ref array, size + 1);
array[size] = SubArrayToAdd;
}
// create a method that goes through all the existing subsets and copies them, adds the item, and adds those copies to the result array
void AddSubsets(object item)
{
// store the length of the result because if we don't we will infinitely expand(because we resize the array)
int currentLength = result.Length;
for (int i = 0; i < currentLength; i++)
{
// copy the array so we don't change the original
object[] previousItemArray = result[i]; // []
// add the item to it
Append(ref previousItemArray, item); // [1]
// add that copy to the results
Append(ref result, previousItemArray); // [[]] -> [[],[1]]
}
}
// Loop over the set and add the subsets to the result
for (int i = 0; i < set.Length; i++)
{
object item = set[i];
AddSubsets(item);
}