数组不重复子集
子集
数组子集,即包含有限个数组元素的集合。
eg. [1,2,3]的子集,[[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
思路
我们之前采用【回溯算法】计算指定长度的数组子集组合。
eg. 在数组 [ 1 , 2 , 3 , 4 , 5 ] [1,2,3,4,5] [1,2,3,4,5]找长度为【3】的数组子集,我们首先确定前两个数,【1,2】然后增加【3】则满足数组长度为3,将这个结果增加到答案中,同时return, 递归弹栈并删除【3】返回上一个状态【1,2】,继续遍历增加【4】,【1,2,4】同样增加到数组中,依次遍历,能够取得所有长度为【3】的子集。
我们只需要循环取长度为 【1~n】(n所给数组长度)的数组子集,即可得到所有数组的子集。
注意,我们需要确保子集不重复,这一点我们只需要保证数组有序就可以实现。
代码实现
import java.util.*;
public class Test{
static ArrayList<ArrayList<Integer>> ans;
public static void func(int [] arr){
//答案数组
ans = new ArrayList<>();
//取不同长度的子集
for(int i=1;i<=arr.length;i++){
func(new ArrayList<Integer>(),i,arr,arr[0]);
}
//java8 流输出
ans.stream().peek(o -> o.toString()).forEach(System.out::print);
}
public static void func(ArrayList<Integer> arr,int size,int[] list,int max){
if(arr.size() == size){
//长度符合要求,递归终止
ans.add(new ArrayList<>(arr));//此处注意保存的数组对象不能直接传arr的引用值
return;
}
for(int i=0;i<list.length;i++){
//循环数组中的值
if(!arr.contains(list[i])&&list[i]>=max){
//确保数组中不包含已经存储的值,如果给定数组中有重复值可以设置下标数组进行此步骤
//同时保证数组中的值大于数组中的最大值,可以避免出现重复子集【1,2】/【2,1】只有【1,2】会出现
max = list[i];//更新最大值
arr.add(list[i]);
func(arr,size,list,max);//递归
arr.remove(arr.size()-1);//回溯
}
}
}
public static void main(String[] args) {
int[] tmp = {1,2,3,4};
func(tmp);
}
}
运行结果
温故知新 未央书斋