打印一组的所有子集

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打印一组的所有子集相关的知识,希望对你有一定的参考价值。

我需要编写一个recursive函数,该函数接收一个数字并打印从1到n的所有子组。我不在乎订单。

例如,如果number = 3我需要输出:


1
2
3
1,2
1,3
2,3
1,2,3

但是我的代码给出了:

1,2,3
2,3
3

这是我的代码,我叫方法subGroups(3);

    public static void subGroups(int num) 
        int[] ar = new int[num];
        subGroups(ar, 1, num);
    

    private static int[] insertToArr(int num, int[] arr) 
        if (num == 0)
            return arr;
        arr[num - 1] = num;
        return insertToArr(num - 1, arr);
    

    private static void subGroups(int[] arr, int start, int end) 
        if (end <= 0 || start > arr.length)
            return;
        else if (start > end)
            subGroups(arr, start, end - 1);
        else 
            if (start != 0) 
                System.out.print("");

                printAll(start, end);
                System.out.println("");
            
            subGroups(arr, start + 1, end);
        

    

    // prints all in in one line recursive
    private static void printAll(int start, int end) 
        if (start < end) 
            System.out.print(start + ",");
            printAll(start + 1, end);
         else 
            System.out.print(start);
        

    

如何获得请求的结果?

答案

这应该工作,请参阅如何将其移植到数组。

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;

import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toList;

public class Main 
    public static void powerset(int n) 
        System.out.println(
                powerset(IntStream.rangeClosed(1, n).boxed().collect(toList()))
        );
    

    public static Set<Set<Integer>> powerset(List<Integer> set) 
        if (set.isEmpty()) 
            Set<Set<Integer>> result = new HashSet();
            result.add(emptySet());
            return result ;
         else 
            Integer element = set.remove(0);
            Set<Set<Integer>> pSetN_1 = powerset(set);

            Set<Set<Integer>> pSet_N= new HashSet();
            pSet_N.addAll(pSetN_1);

            for (Set<Integer> s : pSetN_1) 
                Set<Integer> ss = new HashSet(s);
                ss.add(element);
                pSet_N.add(ss);
            
            return pSet_N;
        
    

    public static void main(String[] args) throws Exception 
        powerset(3); // [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
    

顺便说一句,您正在计算幂集,即集合的所有子集(不是组)的集合

另一答案

如果(start > end)为true,则递归调用subGroups(arr, start, end-1)也将为true,并且递归将沿着该路径继续进行,直到end太小。

所以这里的东西需要改变。考虑到您永远都不会重置startend

另一答案

一些提示,以及下面的代码框架:arr应该用作所找到子集的累加器。它的初始大小为0,每当元素添加到当前子集中时,大小就会增加。

初始呼叫应为:

int[] arr = new int[0];
subGroups(arr, 1, num);

至此,您已经选择了0个元素,仍然需要选择元素的子集1,...,num

函数subGroups应该是:

/*
 * generates all subsets of set start,...,end , union "arr"
 */
private static void subGroups(int[] arr, int start, int end) 
  //terminal condition: print the array
  if (start>end) 
    print(arr);
  
  else 
    //here we have 2 cases: either element "start" is part of the subset, or it isn't

    // case 1: "start" is not part of the subset
    // so "arr" is unchanged
    subGroups(arr, start+1, end);

    // case 2: "start" is part of the subset
    // TODO: create another array, containing all elements of "arr", and "start"
    int[] arrWithStart=copyAndInsert(arr, start);
    subGroups(arrWithStart, start+1, end);
  


private static void print(int[] arr) 
  // TODO code here


/*
 * copy and insert:
 * it should create a new array, with length=arr.length+1,
 * containing all elements of array "arr", and also "element"
 */
static int[] copyAndInsert(int[] arr, int element) 
  // TODO code here

以上是关于打印一组的所有子集的主要内容,如果未能解决你的问题,请参考以下文章

怎么用sql语句获取每一组的第一条记录(包括所有字段,不是单个字段)

搜索技术——子集生成和组合问题

[算法]打印N个数组的整体最大Top K

在C中创建n个项目的k和m个组合的所有可能子集[重复]

枚举所有子集的三种算法详解-《算法入门经典》

如何找出为啥所有数据子集的总和比总和小1