• 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也是这种,事实上本质就是当一个反复元素进来时忽略上一个元素已经有的结果,仅仅考虑由反复元素所产生的新结果。
  • 相关阅读:
    手写vector
    Linux文件寻址算法:逻辑地址到物理地址的转换
    东北大学操作系统实验:进程同步和通信(生产者消费者问题模拟)
    操作系统页面置换算法之FIFO,LRU
    火车进站
    进程状态转换及其PCB的变化
    iOS ViewController里代码结构的规定
    mac下搭建https服务器
    openssl生成证书
    mac下 apacha tomcat相关操作
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6869528.html
Copyright © 2020-2023  润新知