[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;
        }



};

 

 

posted @ 2015-03-13 16:15  穆穆兔兔  阅读(238)  评论(0编辑  收藏  举报