78. Subsets I && 90. Subsets II

来源:互联网 发布:淘宝双11预售规则 编辑:程序博客网 时间:2024/05/06 05:44

------------------------------------------- SUBSETS 1 -------------------------------------------

一、问题描述

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,3], a solution is:

[  [3],  [1],  [2],  [1,2,3],  [1,3],  [2,3],  [1,2],  []]

二、我的解法

参考了别人的解法。

因为要“return all possible subsets”,所以可以用DFS解(不太明白)。

难点在于如何去掉重复set,这里采用的方法是选代表。比如[1,2,3],[3,1,2]...我们选123,因为它排好序了。

递归的时候要处理极端情况。然后回溯的时候记得remove。

代码:

class Solution {    public List<List<Integer>> subsets(int[] nums) {        List<List<Integer>> list = new ArrayList<List<Integer>>();        if(nums == null){            return list;        }        if(nums.length == 0){            list.add(new ArrayList<Integer>());            return list;        }        Arrays.sort(nums);        ArrayList<Integer> subset = new ArrayList<Integer>();        this.recursion(subset, nums, 0, list);        return list;    }    private void recursion(ArrayList<Integer> subset, int[] nums, int startIndex, List<List<Integer>> list){        // deep copy        list.add(new ArrayList<>(subset));        for(int i = startIndex; i < nums.length; i++){            subset.add(nums[i]);            recursion(subset, nums, i+1, list);            // !!!            subset.remove(subset.size()-1);        }    }}


三、其他解法

全部引用自http://bangbingsyb.blogspot.com/2014/11/leetcode-subsets-i-ii.html

1. bit manipulation

由于S[0: n-1]组成的每一个subset,可以看成是对是否包含S[i]的取舍。S[i]只有两种状态,包含在特定subset内,或不包含。所以subset的数量总共有2^n个。所以可以用0~2^n-1的二进制来表示一个subset。二进制中每个0/1表示该位置的S[i]是否包括在当前subset中。


2. 添加数字构建subset

起始subset集为:[]
添加S0后为:[], [S0]
添加S1后为:[], [S0], [S1], [S0, S1]
添加S2后为:[], [S0], [S1], [S0, S1], [S2], [S0, S2], [S1, S2], [S0, S1, S2]
红色subset为每次新增的。显然规律为添加Si后,新增的subset为克隆现有的所有subset,并在它们后面都加上Si。


------------------------------------------- SUBSETS 2 -------------------------------------------

一、问题描述

Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,2], a solution is:

[  [2],  [1],  [1,2,2],  [2,2],  [1,2],  []]

二、我的解法

参考了这篇笔记:http://blog.csdn.net/u011095253/article/details/9158397

和Subset 1的区别在于集合中有重复元素了。如果按照1的方法去做,[1,2,2]的结果是:

[

  [],

  [1],

   [1, 2],

  [1, 2, 2],

  [1, 2]  <= 回溯到subset==[1],又取了第二个2形成新的subset,就重复了

  [2]

  [2, 2]

  [2]  <= 回溯到subset==[],又取了第二个2形成新的subset,就重复了

]

所以和1的区别是,形成新subset之前加判断,是否和之前取的数字一样,如果一样就continue。

class Solution {    public List<List<Integer>> subsetsWithDup(int[] nums) {        List<List<Integer>> result = new ArrayList<List<Integer>>();                if(nums == null){            return result;        }                if(nums.length == 0){            result.add(new ArrayList<Integer>());            return result;        }                Arrays.sort(nums);        List<Integer> subset = new ArrayList<Integer>();        this.recursion(subset, nums, 0, result);                return result;    }        private void recursion(List<Integer> subset,                            int[] nums,                          int startIndex,                          List<List<Integer>> result){        result.add(new ArrayList<Integer>(subset));                for(int i = startIndex; i < nums.length; i ++){            // here is the difference, giving up the redundant numbers            if(i > startIndex && nums[i] == nums[i-1]){                continue;            }            subset.add(nums[i]);            recursion(subset, nums, i + 1, result);            subset.remove(subset.size()-1);        }    }}


四、反思&收获

1. deep copy VS shallow cpy VS clone

https://stackoverflow.com/questions/6182565/deep-copy-shallow-copy-clone

http://www.jianshu.com/p/8d3b4b195501




原创粉丝点击