34 子集(Subsets)

1 题目

题目:子集(Subsets)
描述:给定一个含不同整数的集合,返回其所有的子集。子集中的元素不能以降序排列,解集不能包含重复的子集。

lintcode题号——17,难度——medium

样例1:

输入:nums = [0] 
输出:
[ 
  [], 
  [0] 
] 
解释:
[0]的子集只有[]和[0]。

样例2:

输入:nums = [1,2,3] 
输出:
[ 
  [3], 
  [1], 
  [2], 
  [1,2,3], 
  [1,3], 
  [2,3], 
  [1,2], 
  [] 
] 
解释:
[1,2,3]的子集有[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]。

2 解决方案

2.1 思路

  题目要求得到所有子集,深度优先搜索(Depth First Search)的经典应用场景之一就是在一定的条件下遍历所有解集,考虑使用DFS来解。

DFS常用于需要遍历出所有解的场景中,例如求所有子集、得到所有组合、全排列等经典问题。

2.2 图解

nums = [1,2,3]的情况下,深度优先搜索的图如下:

null
1
2
3
2
3
3
3

每个节点都生成一个子集,得到所有子集:

[null]
[1]
[2]
[3]
[1,2]
[1,3]
[2,3]
[1,2,2]

2.3 时间复杂度

  深度优先搜索的时间复杂度是逻辑图上的节点数(即所有元素的组合数,n个元素,每个元素都有取或不取两种可能,所以是2的n次方)与处理每个节点的耗时(for循环n次)的乘积,该题的算法的时间复杂度为O(2^n * n)。

深度优先搜索的时间复杂度计算没有通用的方式,只能根据具体题目计算,可以理解成看作答案个数与构造每个答案花费的时间的乘积。

2.4 空间复杂度

  使用了vector数据结构保存节点,算法的空间复杂度为O(n)。

3 源码

细节:

  1. 题目要求子集元素按升序排列,所以需要提前排序原数组。

C++版本:

/**
* @param nums: A set of numbers
* @return: A list of lists
*/
vector<vector<int>> subsets(vector<int> &nums) {
    // write your code here
    vector<vector<int>> results;
    if (nums.empty())
    {
        results.push_back(vector<int>());
        return results;
    }

    sort(nums.begin(), nums.end());

    vector<int> path;
    dfs(nums, path, 0, results);
    return results;
}

void dfs(vector<int> & nums, vector<int> path, int startIndex, vector<vector<int>> & results)
{
    results.push_back(path);

    for (int i = startIndex; i < nums.size(); i++)
    {
        path.push_back(nums.at(i));
        dfs(nums, path, i + 1, results);
        path.pop_back();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值