简体   繁体   English

打印数组的所有子集

[英]Print all subsets of an array

I'm trying to print all the subsets of an array.我正在尝试打印数组的所有子集。 For example:例如:

Input: nums = [1,2]
Output:
[[1], [2], [1,2], []]

I've written a recursive approach, given that all such solutions start with a condition and the program calls itself for a sub-array.我编写了一种递归方法,因为所有此类解决方案都以条件开头,并且程序会调用自己的子数组。 But I get a ConcurrentModificationException at for(ArrayList<Integer>subset: subsets2) .但是我在for(ArrayList<Integer>subset: subsets2)得到了ConcurrentModificationException

How to fix the issues and convert it to a working solution?如何解决问题并将其转换为可行的解决方案?

UPDATE: I don't need a working solution.更新:我不需要有效的解决方案。 I need to fix my own code.我需要修复我自己的代码。 Please work on my own code below:请在下面使用我自己的代码:

import java.util.ArrayList;
import java.util.List;

public class TestPractice {
    public static void main(String[] args){
        int[] x = {1,2};
        System.out.println(subsets(x));
    }
    
    public static List<ArrayList<Integer>> subsets(int[] nums) {
        ArrayList<ArrayList<Integer>> subsets = new ArrayList<ArrayList<Integer>>();
        if (nums.length ==1){
            ArrayList<Integer> subset1 = new ArrayList<Integer>();
            ArrayList<Integer> subset2 = new ArrayList<Integer>();
            subset2.add(nums[0]);
            subsets.add(subset1);
            subsets.add(subset2);
            return subsets;
        }
        int[] nums_1 = new int[nums.length-1];
        for(int i = 0; i< nums.length-1; i++) {
        nums_1[i]=nums[i];
        }
        
        List<ArrayList<Integer>> subsets2= subsets(nums_1); 
        //now add nums[n] to all subsets of nums[0:n-1]
        for(ArrayList<Integer>subset: subsets2) {
            ArrayList<Integer> subset1 = new ArrayList<Integer>();
            subset1.add(nums[nums.length-1]);
            subset1.addAll(subset);
            subsets2.add(subset1);
        }
        return subsets2;
    }
    
    
}

Don't add elements to a List when you're iterating over it.迭代列表时不要将元素添加到列表中。 Your code can be greatly simplified by only choosing to either take or not take the current element each time.您的代码可以通过每次仅选择采用或不采用当前元素来大大简化。 Demo演示

public static Set<List<Integer>> subsets(Set<List<Integer>> result, ArrayList<Integer> curr, int[] nums, int idx) {
    result.add((List<Integer>)curr.clone());
    if(idx < nums.length){
         subsets(result, curr, nums, idx + 1);
         final ArrayList<Integer> next = (ArrayList<Integer>) curr.clone();
         next.add(nums[idx]);
         subsets(result, next, nums, idx + 1);
    }
    return result;
}
public static void main(String[] args){
    int[] x = {1,2};
    System.out.println(subsets(new HashSet<>(), new ArrayList<>(), x, 0));
}

You can also use bitmasking.您也可以使用位掩码。 Demo演示

public static Set<List<Integer>> subsets(int[] nums) {
      final Set<List<Integer>> result = new HashSet<>();
      for(int i = 0; i < 1 << nums.length; i++){
         final List<Integer> curr = new ArrayList<>();
         for(int j = 0; j < nums.length; j++){
            if(((i>>j)&1)==1) curr.add(nums[j]);
         }
         result.add(curr);
      }
      return result;
}
public static void main(String[] args){
    int[] x = {1,2,};
    System.out.println(subsets(x));
}

It can be solved using both, Iterative and Recursive Approach它可以使用IterativeRecursive方法来解决

  • For this problem using LinkedList is faster as compared to ArrayList对于这个问题,使用LinkedListArrayList更快
  • Also, you don't need to handle the case when nums.length == 1此外,当nums.length == 1时,您不需要处理这种情况

Iterative Approach迭代方法

import java.util.LinkedList;
import java.util.List;

public class TestPractice {
    public static void main(String[] args) {
        int[] x = { 1, 2 };
        System.out.println(subsets(x));
    }

    public static List<LinkedList<Integer>> subsets(int[] nums) {
        LinkedList<LinkedList<Integer>> subsets = new LinkedList<LinkedList<Integer>>();
        subsets.add(new LinkedList<Integer>());
        for(int i = 0; i < nums.length; i++) {

            LinkedList<LinkedList<Integer>> temp = new LinkedList<LinkedList<Integer>>();
            for(LinkedList<Integer> l1: subsets) {
                LinkedList<Integer> l2 = new LinkedList<Integer>(l1);
                l2.add(nums[i]);
                temp.add(l2);
            }
            subsets.addAll(temp);
        }

        return subsets;
    }
}

Recursive Approach递归方法

import java.util.LinkedList;
import java.util.List;

public class TestPractice {
    public static void main(String[] args) {
        int[] x = { 1, 2 };
        System.out.println(subsets(x));
    }

    public static List<List<Integer>> subsets(int n[]) {
        List<List<Integer>> subsets = new LinkedList<List<Integer>>();
        helper(n, 0, subsets, new LinkedList<Integer>());
        return subsets;
    }

    public static void helper(int[] n, int i, List<List<Integer>> subsets, LinkedList<Integer> subset1) {
        if(i == n.length) {
            subsets.add(subset1);
            return;
        }
        helper(n, i + 1, subsets, subset1);
        LinkedList<Integer> subset2 = new LinkedList<Integer>(subset1);
        subset2.add(n[i]);
        helper(n, i + 1, subsets, subset2);
    }
}

concurrentmodificationexception occurs when you are looping and updating the same list, so create a new list and update that list inside the loop instead of subsets2.add(subset1) . concurrentmodificationexception发生在您循环和更新同一个列表时,因此创建一个新列表并在循环内更新该列表而不是subsets2.add(subset1)

Below I have create a new list result and updating result list inside loop instead of subset2下面我创建了一个新的列表result并在循环内更新result列表而不是subset2

import java.util.ArrayList;
import java.util.List;
public class TestPractice {
    public static void main(String[] args){
        int[] x = {1,2};
        System.out.println(subsets(x));
    }
    
    public static List<ArrayList<Integer>> subsets(int[] nums) {
        ArrayList<ArrayList<Integer>> subsets = new ArrayList<ArrayList<Integer>>();
        if (nums.length ==1){
            ArrayList<Integer> subset1 = new ArrayList<Integer>();
            ArrayList<Integer> subset2 = new ArrayList<Integer>();
            subset2.add(nums[0]);
            subsets.add(subset1);
            subsets.add(subset2);
            return subsets;
        }
        int[] nums_1 = new int[nums.length-1];
        for(int i = 0; i< nums.length-1; i++) {
        nums_1[i]=nums[i];
        }
        
        List<ArrayList<Integer>> subsets2= subsets(nums_1); 
        List<ArrayList<Integer>> result= subsets(nums_1); 
        //now add nums[n] to all subsets of nums[0:n-1]
        for(ArrayList<Integer>subset: subsets2) {
            ArrayList<Integer> subset1 = new ArrayList<Integer>();
            subset1.add(nums[nums.length-1]);
            subset1.addAll(subset);
            result.add(subset1);
        }
        return result;
    }
    
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM