数组---求数组组成的集合的所有子集

题目

给定一个数组,求数组的所有子集,要求每个子集中的元素是升序的;
如:[1,2,3]
则:
[]
[1]
[2]
[3]
[1,2]
[1,3]
[2,3]
[1,2,3]

解法1

递归,利用二叉树思想;
第0层为空集;第i层表示将数组第i个元素是否加入到集合中,左子树表示加入,右子树表示不加入;
最后,每个叶子表示一个子集;如下所示:
[]
[1] []
[1,2] [1] [2] []
[1,2,3] [1,2] [1,3] [1] [2,3] [2] [3] []

图得出:只要原数组有序,就可以保证每个子集有序

level=0 不加a[0],level+1 递归;加入a[0],level+1 递归;
level=1 不加a[1],level+1 递归;加入a[1],level+1 递归;
levle=2 不加a[2],level+1 递归;加入a[2],level+1 递归;
level=3 返回

每次递归中,需要上次的子集,在上次的子集中加入当前元素,所以在递归函数中,需要加入当前子集的参数;
level参数;

实现:

public static ArrayList<ArrayList<Integer>> subsets_1(int[] S){
        ArrayList<Integer> current=new ArrayList<Integer>();
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();

        Arrays.sort(S);  //排序
        subsets_(S,current,0,res);
        return res;
    }
    private static void subsets_(int[] s,ArrayList<Integer> current, int level, ArrayList<ArrayList<Integer>> res) {
        if(level==s.length){
            res.add(new ArrayList<Integer>(current));
            return;
        }
        subsets_(s,new ArrayList<Integer>(current),level+1,res);

        current.add(s[level]);
        subsets_(s,new ArrayList<Integer>(current),level+1,res);
    }

解法2

递归;
求[1,2,3]的全部子集,可以先求出[2,3]的全部子集,然后将在得出的全部子集中,每个加入1,后得到的全部子集+[2,3]的全部子集即为所求;
[2,3]的全部子集也是;

要保证每个子集有序,需要对递归中的每个子集加入结果时,排序

递归函数(a,start)数组,从数组的第几个开始求子集;有返回值-子集的集合;
start=0 递归start++ 对返回的结果中的每个子集,加入结果中;每个子集加入a[0],加入结果中;
start=1 递归start++ 对返回的结果中的每个子集,加入结果中;每个子集加入a[1],加入结果中;
start=2 递归start++ 对返回的结果中的每个子集,加入结果中;每个子集加入a[2],加入结果中;
start=3 结果中加入空集,返回;

实现:

public static ArrayList<ArrayList<Integer>> subsets_2(int[] S){
        Arrays.sort(S);
        return subsets2_(S,0);
    }

    private static ArrayList<ArrayList<Integer>> subsets2_(int[] s, int k) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        if(k==s.length){
            res.add(new ArrayList<Integer>());
            return res;
        }
        ArrayList<ArrayList<Integer>> tmp=subsets2_(s,k+1);
        int a=s[k];
        for(ArrayList<Integer> list:tmp){
            res.add(list);//加入原子集到结果中

            /*原子集中加入a后,再加入到结果中
             * 注意:不能直接在list中加a在加入到结果中,因为这样加入后,res.add(list)中加入的list也会改变
             */
            ArrayList<Integer> t=new ArrayList<Integer>(list);
            t.add(a);
            Collections.sort(t);//注意排序
            res.add(t);
        }

        return res;
    }

解法3

位运算法;
对于包含n个元素的数组,用n位二进制表示;子集中,每个元素存在表示1,不存在表示0;
子集一共全0-全1,所以一共有2^n个;

从0开始到2^n-1
当前的子集;
对每个数进行如下操作:
判断该数的每一位,如果为1,则在当前的子集中加入该位在数组中的对应元素;如果为0,则不加入;
对该数判断完后,将当前的子集加入到结果集中;

实现:

public static ArrayList<ArrayList<Integer>> subsets_3(int[] S){
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();

        Arrays.sort(S);

        int max=1<<S.length;//2^n;
        for(int i=0;i<max;i++){
            ArrayList<Integer> tmp=new ArrayList<Integer>();
            int num=i;

            int count=0;
            //判断num的每一位
            while(num>0){
                if((num&1)==1){
                    tmp.add(S[count]);
                }
                count++;
                num=num>>1;
            }

            res.add(tmp);
        }

        return res;
    }
在C++中,递归是解决此类问题的一种常见方法。下面是一个使用递归函数来找出整型数组所有子集的示例方法: 1. 初始化一个空集合作为当前子集。 2. 从数组的第一个元素开始,对于每一个元素,执行两个操作: - 将当前元素添加到当前子集中。 - 保留当前子集(不添加当前元素),并递归调用函数处理数组中的下一个元素。 3. 继续这个过程,直到数组的所有元素都被处理完毕。 4. 在每个递归步骤中,可以将当前的子集添加到一个列表中(或使用其他方式存储),以便最后获取所有子集。 递归过程结束后,你就得到了所有可能的子集,并且它们已经被存储在了一个新的数据结构中。 以下是一个简单的实现示例代码: ```cpp #include <iostream> #include <vector> void printSubset(const std::vector<int>& subset) { for (int num : subset) { std::cout << num << " "; } std::cout << std::endl; } void findSubsets(int index, const std::vector<int>& set, std::vector<int>& subset, std::vector<std::vector<int>>& allSubsets) { if (index == set.size()) { allSubsets.push_back(subset); return; } // 不包含当前元素的子集 findSubsets(index + 1, set, subset, allSubsets); // 包含当前元素的子集 subset.push_back(set[index]); findSubsets(index + 1, set, subset, allSubsets); subset.pop_back(); // 回溯,移除当前元素以便下一个迭代 } int main() { std::vector<int> set = {1, 2, 3}; // 原始数组 std::vector<std::vector<int>> allSubsets; std::vector<int> subset; // 当前子集 findSubsets(0, set, subset, allSubsets); // 打印所有子集 for (const auto& s : allSubsets) { printSubset(s); } return 0; } ``` 此代码段展示了如何通过递归找到一个整型数组的所有子集,并且将每个子集存储在`allSubsets`向量中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值