zoukankan      html  css  js  c++  java
  • [Leetcode] Subsets

    Given a set of distinct integers, S, return all possible subsets.

    Note:

    • Elements in a subset must be in non-descending order.
    • The solution set must not contain duplicate subsets.

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

    [
      [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]
    
    Hide Tags
     Array Backtracking Bit Manipulation
     
     
    思路:在Combinations的基础上,直接调整k,是k从0到n即可实现subset的功能。
    class Solution {
        vector<vector<int> > m_res;
        vector<int>  m_array;
    public:
        void dfs(int n, int k, int start, vector<int> & in)
        {
            if(k == m_array.size())
            {
                m_res.push_back(m_array);
                return;
            }
            for(int i = start; i < n; i++)
            {
                m_array.push_back(in[i]);
                dfs(n, k, i + 1, in);
                m_array.pop_back();
            }
    
        }
    
        void combine(int n, int elementNum, vector<int> & in)
        {
            dfs(n, elementNum, 0, in);
        }
        public:
            vector<vector<int> > subsets(vector<int> &S) {
    
                sort(S.begin(), S.end());
    
                for(int i = 0; i <= S.size(); i++)
                {
                    combine(S.size(), i,  S);
                    m_array.clear();
                }
    
                return m_res;
            }
    };

     思路二:也可以直接dfs,对于每一个元素都有2种选择,加入或者不加入,其实dfs的关键就是在dfs中的loop是每个元素可以选择的范围,对于这个题目,就是要么加入,要么不加入,可以用for(i=0;i<2;i++)表示。其实就是标准的回溯法子集树问题。

    class Solution {
        vector<vector<int> > m_res;
        vector<int>  m_array;
    public:
    
            void dfs(int dep, vector<int> &S)
            {
                if(dep == S.size())
                {
                    m_res.push_back(m_array);
                    return ;
                }
    
    #if 0
                for(int i = 0; i< 2; i++)
                {
                    // contain the element
                    if(i == 0)
                    {
                        m_array.push_back(S[dep]);
                        dfs(dep + 1, S);
                        m_array.pop_back();
                    }
                    // don't contain the element
                    else
                        dfs(dep + 1, S);
                }
    #else
                // contain the element
                m_array.push_back(S[dep]);
                dfs(dep + 1, S);
                m_array.pop_back();
    
                // don't contain the element
                dfs(dep + 1, S);
    #endif
            }
    
            vector<vector<int> > subsets(vector<int> &S) {
    
                sort(S.begin(), S.end());
    
                dfs(0, S);
    
                return m_res;
            }
    
    
    
    };

     思路3.位向量法,和上面的方法没有本质区别

    // LeetCode, Subsets
    // Î位向量法,深搜,时间复杂度 O(2^n),空间复杂度 O(n)
    class Solution {
        public:
            vector<vector<int> > subsets(vector<int> &S) {
                sort(S.begin(), S.end()); // Êä³öÒªÇóÓÐÐò
                vector<vector<int> > result;
                vector<bool> selected(S.size(), false);
                subsets(S, selected, 0, result);
                return result;
            }   
        private:
            static void subsets(const vector<int> &S, vector<bool> &selected, int step,
                    vector<vector<int> > &result) {
                if (step == S.size()) {
                    vector<int> subset;
                    for (int i = 0; i < S.size(); i++) {
                        if (selected[i]) subset.push_back(S[i]);
                    }   
                    result.push_back(subset);
                    return;
                }   
                // 不选 S[step]
                selected[step] = false;
                subsets(S, selected, step + 1, result);
                // 选 S[step]
                selected[step] = true;
                subsets(S, selected, step + 1, result);
            }   
    };

    思路4,其实是排序树的处理方法:

          m_array.push_back(S[idx]);

                    dfs(idx + 1, S);

                  m_array.pop_back();

    从dep开始,将S[0]加入到m_array中,S[1]加入到m_array中。。。。S[n-1]加入到m_array中。。

    由于 m_res.push_back(m_array);在整个for loop之前,他的意思就是在直接计入到结果中,不包含其他元素。

    以 S = {1,2,3}举例:

    dfs(0),

       |---m_array= {NULL},加入m_res

       |----m_array={1},调用dfs(1),

       |          |---m_array={1},加入m_res,

       |            |---m_array={1,2}调用dfs(2)

       |                    |---m_array={1,2},加入m_res

       |                    |---m_array={1,2,3}, 调用dfs(3)

       |                                  |---m_array={1,2,3},加入m_res,

       |---m_array={2},调用dfs(2),

       |          |---m_array={2},加入m_res,

       |          |---m_array={2,3},调用dfs(3)

       |                      |---m_array={2,3},加入m_res,

       |---m_array={3},调用dfs(3)

                  |---m_array={3},加入m_res

    换句话说,这个思路是,先是空,然后是S[1]开头的,然后是S[2]开头的,S[3]开头的,且S[n]开头的m_array中不包含S[0]...S[n-1]的元素,只包含S[n]...S[size-1],即不包含前面的元素,只包含后面的元素。

    class Solution {
        vector<vector<int> > m_res;
        vector<int>  m_array;
    public:
            void dfs(int dep, vector<int> &S)
            {
                m_res.push_back(m_array);
    
                for(int idx = dep; idx < S.size(); idx ++)
                {
                    m_array.push_back(S[idx]);
                    dfs(idx + 1, S);
                    m_array.pop_back();
                }
            }
    
            vector<vector<int> > subsets(vector<int> &S) {
    
                sort(S.begin(), S.end());
    
                dfs(0, S);
    
                return m_res;
            }
    
    
    
    };
  • 相关阅读:
    Python学习 :面向对象 -- 三大特性
    Python学习 :面向对象(一)
    小米oj #40 找小“3”
    第三次作业
    排序算法模板
    树状数组求逆序数
    最短路模板
    字典树模板
    LCS
    多项式朴素乘法
  • 原文地址:https://www.cnblogs.com/diegodu/p/4335412.html
Copyright © 2011-2022 走看看