【LeetCode】Subsets - Medium

93 篇文章 0 订阅
69 篇文章 0 订阅

给定一个含不同整数的集合,返回其所有的子集、

给定一个含不同整数的集合,返回其所有的子集
注意事项
子集中的元素排列必须是非降序的,解集必须不包含重复的子集
样例
如果 S = [1,2,3],有如下的解:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
挑战
你可以同时用递归与非递归的方式解决么?
标签
递归 优步 脸书
相关题目
中等最小子集 46 % 容易
所有子集的和 16 % 容易
分割字符串 21 % 中等
恢复IP地址 24 % 中等
带重复元素的子集 26 % 中等

(1)Java

// 递归:实现方式,一种实现DFS算法的一种方式
class Solution {
    /**
     * @param S: A set of numbers.
     * @return: A list of lists. All valid subsets.
     */
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> results = new ArrayList<>();

        if (nums == null) {
            return results;
        }

        if (nums.length == 0) {
            results.add(new ArrayList<Integer>());
            return results;
        }

        Arrays.sort(nums);
        helper(new ArrayList<Integer>(), nums, 0, results);
        return results;
    }


    // 递归三要素
    // 1. 递归的定义:在 Nums 中找到所有以 subset 开头的的集合,并放到 results
    private void helper(ArrayList<Integer> subset,
                        int[] nums,
                        int startIndex,
                        List<List<Integer>> results) {
        // 2. 递归的拆解
        // deep copy
        // results.add(subset);
        results.add(new ArrayList<Integer>(subset));

        for (int i = startIndex; i < nums.length; i++) {
            // [1] -> [1,2]
            subset.add(nums[i]);
            // 寻找所有以 [1,2] 开头的集合,并扔到 results
            helper(subset, nums, i + 1, results);
            // [1,2] -> [1]  回溯
            subset.remove(subset.size() - 1);
        }

        // 3. 递归的出口
        // return;
    }
}

// // Non Recursion
// class Solution {
//     /**
//      * @param S: A set of numbers.
//      * @return: A list of lists. All valid subsets.
//      */
//     public List<List<Integer>> subsets(int[] nums) {
//         List<List<Integer>> result = new ArrayList<List<Integer>>();
//         int n = nums.length;
//         Arrays.sort(nums);

//         // 1 << n is 2^n
//         // each subset equals to an binary integer between 0 .. 2^n - 1
//         // 0 -> 000 -> []
//         // 1 -> 001 -> [1]
//         // 2 -> 010 -> [2]
//         // ..
//         // 7 -> 111 -> [1,2,3]
//         for (int i = 0; i < (1 << n); i++) {
//             List<Integer> subset = new ArrayList<Integer>();
//             for (int j = 0; j < n; j++) {
//                 // check whether the jth digit in i's binary representation is 1
//                 if ((i & (1 << j)) != 0) {
//                     subset.add(nums[j]);
//                 }
//             }
//             result.add(subset);
//         }
//         return result;
//     }
// }

(2)C++

class Subsets{
public:
    vector<vector<int>> getSubsets(vector<int>& nums){
        vector<vector<int>> result;
        vector<int> item;
        result.push_back(item);
        generate(0, nums, item, result);
        return result;
    }
private:
    void generate(int i, vector<int>& nums,
                  vector<int>& item,
                  vector<vector<int>> &result){
        if(i >= nums.size()){// 递归终止条件(因为 下标从0起)
            return;
        }
        item.push_back(nums[i]);
        result.push_back(item);// 将当前生成的子集item加入最终结果
        generate(i + 1, nums, item, result);// 第一次递归
        item.pop_back();// 回溯递归要素!递归回溯:放/不放入元素nums[i]
            //  如:item中有[1,2]-->回溯变为item:[1]-->第二次递归后,变为item:[1,3]
        generate(i + 1, nums, item, result);// 第二次递归
    }
};

②class Solution2 {
private:
    void helper(vector<vector<int> > &results,
                vector<int> &subset,
                vector<int> &nums,
                int start) {
        results.push_back(subset);

        for (int i = start; i < nums.size(); i++) {
            subset.push_back(nums[i]);
            helper(results, subset, nums, i + 1);
            subset.pop_back();
        }
    }

public:
    vector<vector<int> > subsets(vector<int> &nums) {
        vector<vector<int> > results;
        vector<int> subset;

        sort(nums.begin(), nums.end());
        helper(results, subset, nums, 0);

        return results;
    }
};

③//位运算版
class Solution3 {
public:
    vector<vector<int>> subsets(vector<int>& nums){
        vector<vector<int>> result;
        int all_set = 1 << nums.size(); //设置全部集合的最大值+1;  1 << n, 即2^n
        for(int i = 0; i < all_set; i++){
            vector<int> item;
            for(int j = 0; j < nums.size(); j++){
                if(i & (1 << j)){
                // 构造数字i代表的集合,个元素存储至item
                    item.push_back(nums[j]);
                }// 整数i代表从0至2^n-1这2^n-1个集合
                // (1 << j)即为构造nums数组的第j个元素
                // 若i & (1 << j)为真,则nums[j]放入item
                result.push_back(item);
            }
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值