10k

46. Subsets & 90 Subsets II

Question1

This question gives us an array and let us output all its subsets.

Algorithm1

We could utilize backtracking since we need to traverse all the elements and put them in and out of to get the results.

Code1

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length == 0) {
            return res;
        }
        helper(res, nums, new ArrayList<>(), 0);
        return res;
    }
    
    private void helper(List<List<Integer>> res, int[] nums, List<Integer> list, int start) {
        res.add(new ArrayList<>(list));
        for(int i = start; i < nums.length; i++) {
            list.add(nums[i]);
            helper(res, nums, list, i);
            list.remove(list.size() - 1);
        }
    }
}

Question2

This question is a follow up of previous one, where we have no duplicate elements. Now we are having duplicate number and the result list need to exclude same result.

Algorithm2

Same thought, use backtracking but do more prune here. There are two ways to exclude the duplicates before this, you need to sort the input array:

  • Each time you put a list into result list, you check if there is duplicates and put the distinct ones to keep uniqueness. If you do not do sort, [2, 1, 2] will have [2, 1] and [1, 2] and we couldn't filter out those duplicate out.
  • Instead of putting the duplicates into list and check when putting into result list, we do this on iteration elements. Because we have sort out all the elements, duplicates will stay together, and we only need to check if nums[i] == nums[i - 1] thus to avoid duplication. This is more effective that the method1.

Code2

class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length == 0) {
            return res;
        }
        Arrays.sort(nums);
        helper(res, nums, new ArrayList<>(), 0);
        return res;
    }
    
    private void helper(List<List<Integer>> res, int[] nums, List<Integer> list, int start) {
        if (!res.contains(list)) {
            res.add(new ArrayList<>(list));
        }
        
        for (int i = start; i < nums.length; i++) {
            list.add(nums[i]);
            helper(res, nums, list, i+1);
            list.remove(list.size() - 1);
        }
        
    }
}

Code3

class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length == 0) return res;
        Arrays.sort(nums);
        helper(res, new ArrayList<>(), nums, 0);
        return res;
    }
    
    private void helper(List<List<Integer>> res, List<Integer> list, int[] nums, int index) {
        res.add(new ArrayList<>(list));
        for (int i = index; i < nums.length; i++) {
            if (i != index && nums[i] == nums[i - 1]) continue;
            list.add(nums[i]);
            helper(res, list, nums, i + 1);
            list.remove(list.size() - 1);
        }
    }
}
Thoughts? Leave a comment