Je veux trouver les sous-ensembles d'un ensemble d'entiers. C'est la première étape de l'algorithme "Sum of Subsets" avec retour en arrière. J'ai écrit le code suivant, mais il ne renvoie pas la réponse correcte:
BTSum(0, nums);
///**************
ArrayList<Integer> list = new ArrayList<Integer>();
public static ArrayList<Integer> BTSum(int n, ArrayList<Integer> numbers) {
if (n == numbers.size()) {
for (Integer integer : list) {
System.out.print(integer+", ");
}
System.out.println("********************");
list.removeAll(list);
System.out.println();
} else {
for (int i = n; i < numbers.size(); i++) {
if (i == numbers.size() - 1) {
list.add(numbers.get(i));
BTSum(i + 1, numbers);
} else {
list.add(numbers.get(i));
for (int j = i+1; j < numbers.size(); j++)
BTSum(j, numbers);
}
}
}
return null;
}
Par exemple, si je veux calculer les sous-ensembles de set = {1, 3, 5} .__, le résultat de ma méthode est le suivant:
1, 3, 5, ********************
5, ********************
3, 5, ********************
5, ********************
3, 5, ********************
5, ********************
Je veux qu'il produise:
1, 3, 5
1, 5
3, 5
5
Je pense que le problème vient de la partie List.removeAll (list); Mais je ne sais pas comment le corriger.
Ce que vous voulez s'appelle un Powerset. Voici une implémentation simple de celle-ci:
public static Set<Set<Integer>> powerSet(Set<Integer> originalSet) {
Set<Set<Integer>> sets = new HashSet<Set<Integer>>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<Integer>());
return sets;
}
List<Integer> list = new ArrayList<Integer>(originalSet);
Integer head = list.get(0);
Set<Integer> rest = new HashSet<Integer>(list.subList(1, list.size()));
for (Set<Integer> set : powerSet(rest)) {
Set<Integer> newSet = new HashSet<Integer>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}
Je vais vous donner un exemple pour expliquer le fonctionnement de l'algorithme pour l'ensemble de pouvoir de {1, 2, 3}
:
{1}
et exécutez powerset pour {2, 3}
; {2}
et exécutez powerset pour {3}
; {3}
et exécutez powerset pour {}
; {}
est {{}}
;{3}
est 3
combiné avec {{}}
= { {}, {3} }
;{2, 3}
est {2}
combiné avec { {}, {3} }
= { {}, {3}, {2}, {2, 3} }
;{1, 2, 3}
est {1}
combiné avec { {}, {3}, {2}, {2, 3} }
= { {}, {3}, {2}, {2, 3}, {1}, {3, 1}, {2, 1}, {2, 3, 1} }
.Juste une introduction comment vous pourriez résoudre le problème:
Bien sûr, vous devez vérifier le cas de base, c’est-à-dire si votre liste de numéros est vide.
C'est un fait bien connu qu'un ensemble avec des éléments n
a des sous-ensembles 2^n
. Ainsi, vous pouvez compter en binaire de 0
à 2^n
et interpréter le nombre binaire comme le sous-ensemble correspondant. Notez que cette approche nécessite un nombre binaire avec un nombre suffisant de chiffres pour représenter l'ensemble.
Convertir l’une des deux approches en code ne devrait pas être un gros problème.
Votre code est vraiment déroutant et il n'y a pas d'explication.
Vous pouvez le faire de manière itérative avec un masque de bits qui détermine les nombres figurant dans l'ensemble. Chaque nombre de 0 à 2 ^ n donne un sous-ensemble unique dans sa représentation binaire, par exemple
pour n = 3:
i = 5 -> 101 en binaire, choisissez le premier et le dernier élément i = 7 -> 111 en binaire, choisissez les 3 premiers éléments
Supposons qu'il y ait n éléments (n <64, après tout si n est supérieur à 64, vous exécuterez cela pour toujours).
for(long i = 0; i < (1<<n); i++){
ArrayList<Integer> subset = new ArrayList<Integer>();
for(int j = 0; j < n; j++){
if((i>>j) & 1) == 1){ // bit j is on
subset.add(numbers.get(j));
}
}
// print subset
}
Considérant un visiteur de Noob (merci à Google) à cette question - comme moi
Voici une solution récursive qui fonctionne sur un principe simple:
Set = {a, b, c, d, e}
alors nous pouvons le casser en {a}
+ Subset of {b,c,d,e}
public class Powerset{
String str = "abcd"; //our string
public static void main(String []args){
Powerset ps = new Powerset();
for(int i = 0; i< ps.str.length();i++){ //traverse through all characters
ps.subs("",i);
}
}
void subs(String substr,int index)
{
String s = ""+str.charAt(index); //very important, create a variable on each stack
s = substr+s; //append the subset so far
System.out.println(s); //print
for(int i=index+1;i<str.length();i++)
subs(s,i); //call recursively
}
}
SORTIE
a
ab
abc
abcd
abd
ac
acd
ad
b
bc
bcd
bd
c
cd
d
Il est clair que le nombre total de sous-ensembles d'un ensemble donné est égal à 2 ^ (nombre d'éléments dans l'ensemble). Si défini
A = {1, 2, 3}
alors le sous-ensemble de A est:
{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}
Si nous regardons c'est comme des nombres binaires.
{000}, {001}, {010}, {011}, {100}, {101}, {110}, {111}
Si nous prenons en compte ci-dessus:
static void subSet(char[] set) {
int c = set.length;
for (int i = 0; i < (1 << c); i++) {
System.out.print("{");
for (int j = 0; j < c; j++) {
if ((i & (1 << j)) > 0) {
System.out.print(set[j] + " ");
}
}
System.out.println("}");
}
}
public static void main(String[] args) {
char c[] = {'a', 'b', 'c'};
subSet(c);
}
D'après ce que j'ai appris aujourd'hui, voici la solution JavaIl est basé sur recursion
public class Powerset {
public static void main(String[] args) {
final List<List<String>> allSubsets = powerSet(Arrays.asList(1, 2, 3, 4), 0);
for (List<String> subsets : allSubsets) {
System.out.println(subsets);
}
}
private static List<List<String>> powerSet(final List<Integer> values,
int index) {
if (index == values.size()) {
return new ArrayList<>();
}
int val = values.get(index);
List<List<String>> subset = powerSet(values, index + 1);
List<List<String>> returnList = new ArrayList<>();
returnList.add(Arrays.asList(String.valueOf(val)));
returnList.addAll(subset);
for (final List<String> subsetValues : subset) {
for (final String subsetValue : subsetValues) {
returnList.add(Arrays.asList(val + "," + subsetValue));
}
}
return returnList;
}
}
Son exécution donnera des résultats en tant que
[1]
[2]
[3]
[4]
[3,4]
[2,3]
[2,4]
[2,3,4]
[1,2]
[1,3]
[1,4]
[1,3,4]
[1,2,3]
[1,2,4]
[1,2,3,4]
private static void findSubsets(int array[])
{
int numOfSubsets = 1 << array.length;
for(int i = 0; i < numOfSubsets; i++)
{
int pos = array.length - 1;
int bitmask = i;
System.out.print("{");
while(bitmask > 0)
{
if((bitmask & 1) == 1)
System.out.print(array[pos]+",");
bitmask >>= 1;
pos--;
}
System.out.print("}");
}
}
J'essayais en fait de résoudre celui-ci et j'ai obtenu l'algorithme @phimuemue dans le post précédent. Voici ce que j'ai implémenté. J'espère que ça marche.
/**
*@Sherin Syriac
*
*/
import Java.util.ArrayList;
import Java.util.List;
public class SubSet {
ArrayList<List<Integer>> allSubset = new ArrayList<List<Integer>>();
/**
* @param args
*/
public static void main(String[] args) {
SubSet subSet = new SubSet();
ArrayList<Integer> set = new ArrayList<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
subSet.getSubSet(set, 0);
for (List<Integer> list : subSet.allSubset) {
System.out.print("{");
for (Integer element : list) {
System.out.print(element);
}
System.out.println("}");
}
}
public void getSubSet(ArrayList<Integer> set, int index) {
if (set.size() == index) {
ArrayList<Integer> temp = new ArrayList<Integer>();
allSubset.add(temp);
} else {
getSubSet(set, index + 1);
ArrayList<List<Integer>> tempAllSubsets = new ArrayList<List<Integer>>();
for (List subset : allSubset) {
ArrayList<Integer> newList = new ArrayList<Integer>();
newList.addAll(subset);
newList.add(set.get(index));
tempAllSubsets.add(newList);
}
allSubset.addAll(tempAllSubsets);
}
}
}
public static ArrayList<ArrayList<Integer>> powerSet(List<Integer> intList) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
result.add(new ArrayList<Integer>());
for (int i : intList) {
ArrayList<ArrayList<Integer>> temp = new ArrayList<ArrayList<Integer>>();
for (ArrayList<Integer> innerList : result) {
innerList = new ArrayList<Integer>(innerList);
innerList.add(i);
temp.add(innerList);
}
result.addAll(temp);
}
return result;
}
Si vous traitez avec une vaste collection d'éléments, vous pouvez (bien que ce ne soit probablement pas le cas) rencontrer des problèmes de débordement de pile. J'admets que vous manquerez probablement de mémoire avant de surcharger la pile, mais je vais quand même mettre cette méthode non récursive ici.
public static final <T> Set<Set<T>> powerSet(final Iterable<T> original) {
Set<Set<T>> sets = new HashSet<>();
sets.add(new HashSet<>());
for (final T value : original) {
final Set<Set<T>> newSets = new HashSet<>(sets);
for (final Set<T> set : sets) {
final Set<T> newSet = new HashSet<>(set);
newSet.add(value);
newSets.add(newSet);
}
sets = newSets;
}
return sets;
}
Ou si vous préférez traiter avec des tableaux:
@SuppressWarnings("unchecked")
public static final <T> T[][] powerSet(final T... original) {
T[][] sets = (T[][]) Array.newInstance(original.getClass(), 1);
sets[0] = Arrays.copyOf(original, 0);
for (final T value : original) {
final int oldLength = sets.length;
sets = Arrays.copyOf(sets, oldLength * 2);
for (int i = 0; i < oldLength; i++) {
final T[] oldArray = sets[i];
final T[] newArray = Arrays.copyOf(oldArray, oldArray.length + 1);
newArray[oldArray.length] = value;
sets[i + oldLength] = newArray;
}
}
return sets;
}
// subsets for the set of 5,9,8
import Java.util.ArrayList;
import Java.util.List;
public class Subset {
public static void main(String[] args) {
List<Integer> s = new ArrayList<Integer>();
s.add(9);
s.add(5);
s.add(8);
int setSize = s.size();
int finalValue = (int) (Math.pow(2, setSize));
String bValue = "";
for (int i = 0; i < finalValue; i++) {
bValue = Integer.toBinaryString(i);
int bValueSize = bValue.length();
for (int k = 0; k < (setSize - bValueSize); k++) {
bValue = "0" + bValue;
}
System.out.print("{ ");
for (int j = 0; j < setSize; j++) {
if (bValue.charAt(j) == '1') {
System.out.print((s.get(j)) + " ");
}
}
System.out.print("} ");
}
}
}
//Output : { } { 8 } { 5 } { 5 8 } { 9 } { 9 8 } { 9 5 } { 9 5 8 }
Voici un pseudocode. Vous pouvez couper les mêmes appels récursifs en stockant les valeurs de chaque appel au fur et à mesure et avant de vérifier les appels récursifs si la valeur de l'appel est déjà présente.
L'algorithme suivant aura tous les sous-ensembles à l'exclusion de l'ensemble vide.
list * subsets(string s, list * v){
if(s.length() == 1){
list.add(s);
return v;
}
else
{
list * temp = subsets(s[1 to length-1], v);
int length = temp->size();
for(int i=0;i<length;i++){
temp.add(s[0]+temp[i]);
}
list.add(s[0]);
return temp;
}
}