2011-08-26 26 views
9

Tengo una lista de elementos (1, 2, 3), y que necesito para obtener el superconjunto (powerset) de esa lista (sin repetición de elementos). Así que, básicamente, lo que necesito para crear una lista de listas que se parece a:Impresión de todos los posibles subconjuntos de una lista

{1} 
{2} 
{3} 
{1, 2} 
{1, 3} 
{2, 3} 
{1, 2, 3} 

¿Cuál es la mejor (la simplicidad> eficiencia en este caso, la lista no va a ser enorme) forma de implementar esto? Preferiblemente en Java, pero una solución en cualquier idioma sería útil.

+1

Usted desea que todos los subconjuntos de esa lista. Sugeriría la recursión. Sin embargo, si se trata de, por ejemplo, más de 30-40 elementos, usted no será capaz de hacer frente a la enorme (más de 1 TB de datos) que tiene. ¿Para qué se usa esto? –

+2

Esta estructura de datos que está buscando se llama una Powerset (la diferencia más es que también contiene un conjunto vacío). Ya ha sido discutido en SO. Gracias –

+0

zenzen para señalarme en la dirección correcta ... Me encontraron http://stackoverflow.com/questions/1670862/obtaining-powerset-of-a-set-in-java. – Steve

Respuesta

31

Use máscaras de bits:

int allMasks = (1 << N); 
for (int i = 1; i < allMasks; i++) 
{ 
    for (int j = 0; j < N; j++) 
     if ((i & (1 << j)) > 0) //The j-th element is used 
      System.out.print((j + 1) + " "); 

    System.out.println(); 
} 

Aquí están todas las máscaras de bits:

1 = 001 = {1} 
2 = 010 = {2} 
3 = 011 = {1, 2} 
4 = 100 = {3} 
5 = 101 = {1, 3} 
6 = 110 = {2, 3} 
7 = 111 = {1, 2, 3} 

que conoces en binario el primer bit es el más a la derecha.

+0

Esto es muy interesante ... eres obviamente, mucho más inteligente que yo, aunque - Dame un poco de tiempo para envolver mi mente alrededor de esto .... es N el número de elementos en la lista original? ¿Y estoy mapeando los objetos en mi lista a enteros? – Steve

+0

@Steve - Sí, 'N' es la cantidad de elementos, en su ejemplo anterior' N = 3'. Piensa en binario: el bit es 0 si el elemento no se usa y el bit es 1 si se usa el elemento. Por ejemplo 5 = 101 en binario. Esto significa que se usan '1' y' 3'. '= {1, 3}' –

+0

@Steve - Mira mi edición. –

1
import java.io.*; 
import java.util.*; 
class subsets 
{ 
    static String list[]; 
    public static void process(int n) 
    { 
     int i,j,k; 
     String s=""; 
     displaySubset(s); 
     for(i=0;i<n;i++) 
     { 
      for(j=0;j<n-i;j++) 
      { 
       k=j+i; 
       for(int m=j;m<=k;m++) 
       { 
        s=s+m; 
       } 
       displaySubset(s); 
       s=""; 
      } 
     } 
    } 
    public static void displaySubset(String s) 
    { 
     String set=""; 
     for(int i=0;i<s.length();i++) 
     { 
      String m=""+s.charAt(i); 
      int num=Integer.parseInt(m); 
      if(i==s.length()-1) 
       set=set+list[num]; 
      else 
       set=set+list[num]+","; 
     } 
     set="{"+set+"}"; 
     System.out.println(set); 
    } 
    public static void main() 
    { 
     Scanner sc=new Scanner(System.in); 
     System.out.println("Input ur list"); 
     String slist=sc.nextLine(); 
     int len=slist.length(); 
     slist=slist.substring(1,len-1); 
     StringTokenizer st=new StringTokenizer(slist,","); 
     int n=st.countTokens(); 
     list=new String[n]; 
     for(int i=0;i<n;i++) 
     { 
      list[i]=st.nextToken(); 
     } 
     process(n); 
    } 
} 
+0

El programa es simple. Primero, tratamos de obtener todas las combinaciones posibles de números de 1-n dígitos hasta el último dígito de cada lista de 1,2,3, .... n el número de dígitos es n. Y luego con cada combinación para extraer cada uno de sus caracteres (es decir, el número) y mostrar el elemento del subconjunto almacenado en el índice de la celda denotado por este carácter (número). –

+0

Sería mejor agregar la descripción del código en la respuesta que en los comentarios. Responder con código solo no se considera una buena respuesta por parte de la comunidad en general, incluso el código responde correctamente la pregunta. –

0

de una solución Java basado en la solución Minchev Petar -

public static List<List<Integer>> getAllSubsets(List<Integer> input) { 
    int allMasks = 1 << input.size(); 
    List<List<Integer>> output = new ArrayList<List<Integer>>(); 
    for(int i=0;i<allMasks;i++) { 
     List<Integer> sub = new ArrayList<Integer>(); 
     for(int j=0;j<input.size();j++) { 
      if((i & (1 << j)) > 0) { 
       sub.add(input.get(j)); 
      } 
     } 
     output.add(sub); 
    } 

    return output; 
} 
0

me he dado cuenta de que las respuestas se centran en la lista de cadenas. En consecuencia, decidí compartir una respuesta más genérica. Espero que sea bastante útil. (soultion se basa en otras soluciones que he encontrado, he combinado a un algorithem genérico.)

/** 
* metod returns all the sublists of a given list 
* the method assumes all object are different 
* no matter the type of the list (generics) 
* @param list the list to return all the sublist of 
* @param <T> 
* @return list of the different sublists that can be made from the list object 
*/ 
public static <T> List<List<T>>getAllSubLists(List<T>list) 
{ 
    List<T>subList; 
    List<List<T>>res = new ArrayList<>(); 
    List<List<Integer>> indexes = allSubListIndexes(list.size()); 
    for(List<Integer> subListIndexes:indexes) 
    { 
     subList=new ArrayList<>(); 
     for(int index:subListIndexes) 
      subList.add(list.get(index)); 
     res.add(subList); 
    } 
    return res; 
} 
/** 
* method returns list of list of integers representing the indexes of all the sublists in a N size list 
* @param n the size of the list 
* @return list of list of integers of indexes of the sublist 
*/ 
public static List<List<Integer>> allSubListIndexes(int n) { 
    List<List<Integer>> res = new ArrayList<>(); 
    int allMasks = (1 << n); 
    for (int i = 1; i < allMasks; i++) 
    { 
     res.add(new ArrayList<>()); 
     for (int j = 0; j < n; j++) 
      if ((i & (1 << j)) > 0) 
       res.get(i-1).add(j); 

    } 
    return res; 
} 
Cuestiones relacionadas