Subsets II -- LeetCode

原題鏈接: http://oj.leetcode.com/problems/subsets-ii/

這道題跟Subsets一樣是經典的NP問題--求子集。比Subsets稍微複雜一些的是這裏的集合中可能出現重複元素,因此我們在求子集的時候要避免出現重複的子集。在Subsets中我們每次加進一個元素就會把原來的子集都加上這個元素,然後再加入到結果集中,但是這樣重複的元素就會產生重複的子集。爲了避免這樣的重複,需要用個小技巧。

其實比較簡單,就是每當遇到重複元素的時候我們就只把當前結果集的後半部分加上當前元素加入到結果集中,因爲後半部分就是上一步中加入這個元素的所有子集,上一步這個元素已經加入過了,前半部分如果再加就會出現重複。所以算法上複雜度上沒有提高,反而少了一些操作,就是遇到重複時少做一半,不過這裏要對元素集合先排序,否則不好判斷重複元素。同樣的還是可以用遞歸和非遞歸來解,不過對於重複元素的處理是一樣的。遞歸的代碼如下:
public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
    if(num == null)
        return null;
    Arrays.sort(num);
    ArrayList<Integer> lastSize = new ArrayList<Integer>();
    lastSize.add(0);
    return helper(num, num.length-1, lastSize);
}
private ArrayList<ArrayList<Integer>> helper(int[] num, int index, ArrayList<Integer> lastSize)
{
    if(index == -1)
    {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> elem = new ArrayList<Integer>();
        res.add(elem);
        return res;
    }
    ArrayList<ArrayList<Integer>> res = helper(num,index-1,lastSize);
    int size = res.size();
    int start = 0;
    if(index>0 && num[index]==num[index-1])
        start = lastSize.get(0);
    for(int i=start;i<size;i++)
    {
        ArrayList<Integer> elem = new ArrayList<Integer>(res.get(i));
        elem.add(num[index]);
        res.add(elem);
    }
    lastSize.set(0,size);
    return res;
}
非遞歸的代碼如下:
public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
    ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    res.add(new ArrayList<Integer>());
    if(num==null || num.length==0)
        return res;
    Arrays.sort(num);
    int start = 0;
    for(int i=0;i<num.length;i++)
    {
        int size = res.size();
        for(int j=start;j<size;j++)
        {
            ArrayList<Integer> newItem = new ArrayList<Integer>(res.get(j));
            newItem.add(num[i]);
            res.add(newItem);
        }
        if(i<num.length-1 && num[i]==num[i+1])
        {
            start = size;
        }
        else
        {
            start = 0;
        }
    }
    return res;
}
這種NP問題的重複處理在LeetCode有一定出現頻率,比如還有Permutations II也是這樣的,其實本質就是當一個重複元素進來時忽略上一個元素已經有的結果,只考慮由重複元素所產生的新結果。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章