集合的子集

请编写一个方法,返回某集合的所有非空子集。

给定一个int数组A和数组的大小int n,请返回A的所有非空子集。保证A的元素个数小于等于20,且元素互异。各子集内部从大到小排序,子集之间字典逆序排序,见样例。

[123,456,789]

子集:{[789,456,123],[789,456],[789,123],[789],[456 123],[456],[123]}


集合的每个元素都可以通过bit来表示 

1表示有这个数 0表示没有这个数

子集可以通过二进制的方式表示

1 1 1  7       789,456,123

1 1 0  6       789,456

1 0 1  5       789,123

1 0 0  4       789

0 1 1  3       456 123

0 1 0  2       456

0 0 1  1       123

0 0 0  0       空集

所以这个问题可以转化为:怎样可以从大到小的遍历二进制?

int i=(1<<n)-1

for(int i=i;i>=0;i-—){

for(int j=n-1;j>=0;j-—){

if((i&1<<j)>0){

 集合里面有这个数 加入进去

}}

}

完整代码:

import java.util.*;


public class Subset {

    public ArrayList<ArrayList<Integer>> getSubsets(int[] A, int n) {   

ArrayList<ArrayList<Integer>> res = new  ArrayList<ArrayList<Integer>>();

         if(n==0){//合法性检测

return res;

}

Arrays.sort(A);//排序从小到大

swap(A,0,n-1);//排序从大到小

int start = (1<<n)-1;

for(int i=start;i>0;i--){//遍历二进制的方法

ArrayList<Integer> item = new ArrayList<Integer>();

for(int j=n-1;j>=0;j--){//保证从大到小序列间有序

if((i&(1<<j))>0){

item.add(A[n-1-j]);

}

}

res.add(item);  

}

return res;   

    }

    public void swap(int[] A,int start,int end){

while(start<end){

if(A[start]<A[end]){

A[start] = A[start]^A[end];

A[end] = A[start]^A[end];

A[start] = A[start]^A[end];

}

start++;

end--;

}

 

}

}

题目链接:http://www.nowcoder.com/practice/1f2700e2b1904254b55765479e9b8766?rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值