zoukankan      html  css  js  c++  java
  • 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也是这种,事实上本质就是当一个反复元素进来时忽略上一个元素已经有的结果,仅仅考虑由反复元素所产生的新结果。
  • 相关阅读:
    第一章 概述
    Angular-----代码风格指南!!!(很重要)
    Angular中innerHTML标签的样式不起作用详解
    maven入门
    vue解惑之v-on(事件监听指令)
    vue解惑之slot(插槽)
    js中关于constructor与prototype的理解
    Angular--AOT和JIT两种编译方式带来的改变
    ArcGIS API for JavaScript小白入门
    ionic项目使用Google FCM插件和Google maps插件打包android报错冲突问题
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6869528.html
Copyright © 2011-2022 走看看