LC 78. Subsets 求子集的递归和迭代解法

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

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

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

(1)  递归
递归的思路很清晰,直接上代码:
void genSubsets(vector<vector<int>>& res, vector<int>& cur, vector<int>& nums, int pos) {
    res.push_back(cur);
    for (int i = pos; i < nums.size(); i++) {
        cur.push_back(nums[i]);
        genSubsets(res, cur, nums, i + 1);
        cur.pop_back();
    }
}
vector<vector<int>> subsets(vector<int>& nums) {
    vector<vector<int>> res;
    vector<int> cur;
    genSubsets(res, cur, nums, 0);
    return res;
}
代码和之前的 permutation / combination 非常相似,事实上递归解题方法中的递归题都非常相似。不同的题目的区别在于:1. 何时将cur保存进结果 2. 何时return 3. 下一次递归传入什么样的参数 。这题中,1. 每次进入genSubsets都相当于走到遍历树上的一个节点,此时都进行一次 res.push_back(cur); 2. 深度遍历下去一直到没有候选元素就return,即pos指向nums的最后一个数;3. 下一次递归的nums中不应该有之前出现过的数字,所以下一次开始遍历的pos比当前pos大1.

(2) 迭代

This problem can also be solved iteratively. Take [1, 2, 3] in the problem statement as an example. The process of generating all the subsets is like:

//    Initially: [[]]

//    Adding the first number to all the existed subsets: [[], [1]];

//    Adding the second number to all the existed subsets: [[], [1], [2], [1, 2]];

//    Adding the third number to all the existed subsets: [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]].

代码:

vector<vector<int>> subsets(vector<int>& nums) {
    vector<vector<int>> subs(1, vector<int>());
    for (int i = 0; i < nums.size(); i++) {
        int n = (int)subs.size();
        for (int j = 0; j < n; j++) {
            subs.push_back(subs[j]); // copy a new subs[j]
            subs.back().push_back(nums[i]); // expand the just being created subs[j] with nums[i]
        }
    }
    return subs;
}



每次先将已有的项拷贝一个出来,然后在其上追加当前遍历到的nums[i]。


两种方法都可以,我只想到了第一种,因为在我的印象里我都是按照第一种方法求subsets的。当然看到迭代的写法时才意识到可以这样求subsets,然后按照这个思路的代码就是顺其自然的事了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值