代码随想录 LeetCode 78. 子集

题目
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

解题思路一
本题可用两种方法实现,容易想到的是利用for循环和回溯法对数组nums遍历,因为要求不能包含重复的子集,则for循环时需要设置startIndex,每次回溯,startinde+1. 回溯的终止条件为startIndex大于等于nums大小。该方法的实现如下。

代码实现一

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int>& nums, int startIndex) {
        result.push_back(path); // 收集子集,要放在终止添加的上面,否则会漏掉自己
        if (startIndex >= nums.size()) {
            return;
        }
        for (int i = startIndex; i < nums.size(); i++) {
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        result.clear();
        path.clear();
        backtracking(nums, 0);
        return result;
    }
};

解题思路二
使用一个循环从 0 到 2^n-1,对于每个数字的二进制表示,把对应位置上为 1 的元素加入到当前子集中。
这种方法的时间复杂度是 O(n * 2^n),与原来的算法相同,但由于没有递归的开销,所以实际运行速度更快。
外层循环变量 i 从 0 到 2^n-1,表示所有可能的子集情况。内层循环变量 j 遍历数组 nums 中的每个元素,检查 i 的二进制表示中的每一位是否为 1。如果为 1,则将对应位置上的元素加入到当前子集中。

代码实现二

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> result;
        
        for (int i = 0; i < pow(2, n); i++) {
            vector<int> subset;
            for (int j = 0; j < n; j++) {
                if ((i >> j) & 1) { // 检查第 j 位是否为 1
                    subset.push_back(nums[j]);
                }
            }
            result.push_back(subset);
        }
        
        return result;
    }
};

你可能感兴趣的:(代码随想录训练营,leetcode,算法,数据结构)