转载:三种实现集合求子集合算法

以下内容转载自:ITeye narutolby 的日志
略有调整,不影响主体内容,仅供参考学习。

题目:给定一个集合,求该集合的所有子集合,如集合{1,2}的子集合有{}(空集是所有集合的子集),{1},{2},{1,2},共2^2个子集合,下面给出两种解法,其中第一种解法分递归与非递归实现,都用java实现
【第一种解法】
算法思想:给定一个集合,求子集合过程可分为以下两个步骤:
(1)把集合分为两部分,第一个元素和剩余元素,如{1,2,3}分为1和{2,3}
(2)原集合的所有子集合为剩余元素的子集合并上把第一个元素加入所有子集合,如{2,3}的子集合为{2},{3},{2,3},{},那么把第一个元素1加入这些子集合,则构成{1,2},{1,3},{1,2,3},{1},把这些集合合并起来,则原集合的所有子集合便为{2},{3},{2,3},{},{1,2},{1,3},{1,2,3},{1},代码如下:

// 非递归方式
    static ArrayList<ArrayList<String>> getSub(String args[])
    {
        ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
        ArrayList<ArrayList<String>> temp = null;
        ArrayList<String> element = null;
        //添加为空的子集
        result.add(new ArrayList<String>());

        for (int i = 0; i < args.length; i++)
        {
            temp = new ArrayList<ArrayList<String>>();
            for (int j = 0; j < result.size(); j++)
            {
                element = new ArrayList<String>();
                element.add(args[i]);
                element.addAll(result.get(j));
                temp.add(element);
            }
            result.addAll(temp);
        }
        return result;
    }
// 采用递归算法
    static ArrayList<ArrayList<String>> getSub2(String args[], int index)
    {

        ArrayList<ArrayList<String>> result = null;
        ArrayList<ArrayList<String>> temp = null;
        ArrayList<String> element = null;
        String item = null;
        if (args.length == index)
        {
            result = new ArrayList<ArrayList<String>>();
            result.add(new ArrayList<String>());
        }
        else
        {
            result = getSub2(args, index + 1);
            item = args[index];
            temp = new ArrayList<ArrayList<String>>();
            for (ArrayList<String> sub2 : result)
            {
                element = new ArrayList<String>();
                element.addAll(sub2);
                element.add(item);
                temp.add(element);
            }
            result.addAll(temp);
        }
        return result;
    }

【第二种解法】
算法思想:n个元素的集合,在构造子集合过程中,每个元素有两种情况,在子集合中“存在”与“不存在”,“存在”用“1”表示,“不存在”用“0”表示,这样共有2^n种情况,即2^n个子集合。此时我们想到用长度为n的二进制数字 “1111….000…”,1表示该位置在子集合中存在,0表示该位置在子集合中不存在,让该二进制数从0 一直加到 2^n,则所有情况都会出现,代码如下

// 通过二进制的方法
    static ArrayList<ArrayList<String>> getSub3(String args[])
    {
        ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
        ArrayList<String> subList = null;
        int max = 1 << args.length;

        for (int i = 0; i < max; i++)
        {
            subList = new ArrayList<String>();

            int k = i;
            int index = 0;
            while (k > 0)
            {
                if ((k & 1) > 0)
                {
                    subList.add(args[index]);
                }
                k >>= 1;
                index++;
            }
            result.add(subList);
        }
        return result;
    }

测试方法

public static void main(String[] args)
    {
        String array[] =
        {
                "a", "b", "c", "d"
        };
        ArrayList<ArrayList<String>> list = null;
        //list = getSub(array);
        // list = getSub2(array, 0);
         list = getSub3(array);
        for (int i = 0; i < list.size(); i++)
        {
            ArrayList<String> subList = list.get(i);
            System.out.println(subList.toString());
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值