LeetCode 78:子集生成全攻略

题目LeetCode78

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

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

示例 1:

输入: nums = 1,2,3
输出:\[,1,2,1,2,3,1,3,2,3,1,2,3]

Python解法

解法一(追加)

python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = [[]]
        for num in nums:
            for i in range(len(res)):
                res.append(res[i] + [num])
        return res

解释

在空集的基础上,循环追加后面的数据

python 复制代码
for num in nums:
    # 把当前结果里的每个子集都拿出来,加上 num,再放回 res
    for i in range(len(res)):
        res.append(res[i] + [num])

过程演示

以示例为例。

① 处理第一个数:1

把 res 里的每个子集 + 1,再追加进去:

  • \] + \[1\] = \[1

res 变成:[ [], [1] ]


② 处理第二个数:2

把当前 res 里的每个子集 + 2:

  • \] + \[2\] = \[2

  • 1\] + \[2\] = \[1,2

res 变成:[ [], [1], [2], [1,2] ]


③ 处理第三个数:3

把当前 res 里的每个子集 + 3:

  • \] + \[3\] = \[3

  • 1\] + \[3\] = \[1,3

  • 2\] + \[3\] = \[2,3

  • 1,2\] + \[3\] = \[1,2,3

res 最终:[ [], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3] ]

解法二(搜索)

python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        self.dfs(nums, 0, [], res)
        return res
    def dfs(self, nums, index, path, res):
        res.append(path.copy())
        for i in range(index, len(nums)):
            path.append(nums[i])
            self.dfs(nums, i + 1, path, res)
            path.pop()

解释

index:当前走到第几个数

path:当前正在选的子集

res:最终结果

主要是搜索函数。

python 复制代码
    def dfs(self, nums, index, path, res):
        # 每一步都把当前路径加入答案
        res.append(path.copy())
        
        # 从 index 开始往后选
        for i in range(index, len(nums)):
            path.append(nums[i])       # 选 nums[i]
            self.dfs(nums, i + 1, path, res) # 递归往后
            path.pop()                 # 不选 nums[i],回溯

过程演示

  • 一开始:path = [] → 存 []
  • 选 1 → path = [1] → 存 [1]
    • 再选 2 → path = [1,2] → 存 [1,2]
      • 再选 3 → path = [1,2,3] → 存 [1,2,3]
      • 不选 3 → 退回
    • 不选 2,选 3 → path = [1,3] → 存 [1,3]
  • 不选 1,选 2 → path = [2] → 存 [2]
    • 再选 3 → path = [2,3] → 存 [2,3]
  • 不选 1、2,选 3 → path = [3] → 存 [3]

最后:\[, 1, 1,2, 1,2,3, 1,3, 2, 2,3, 3]

Java解法

解法一(追加)

java 复制代码
import java.util.List;
import java.util.ArrayList;

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        // 初始加入空集合
        res.add(new ArrayList<>());

        // 标准普通for遍历每个数字
        for (int k = 0; k < nums.length; k++) {
            int num = nums[k];
            int size = res.size();
            // 遍历当前已存在的所有子集
            for (int i = 0; i < size; i++) {
                // 复制原有子集
                List<Integer> temp = new ArrayList<>(res.get(i));
                temp.add(num);
                res.add(temp);
            }
        }
        return res;
    }
}

解法二(搜索)

java 复制代码
class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        backtrack(nums, 0, new ArrayList<>(), res);
        return res;
    }

    private void backtrack(int[] nums, int index, List<Integer> path, List<List<Integer>> res) {
        res.add(new ArrayList<>(path));
        for (int i = index; i < nums.length; i++) {
            path.add(nums[i]);
            backtrack(nums, i + 1, path, res);
            path.remove(path.size() - 1);
        }
    }
}

C++解法

解法一(追加)

cpp 复制代码
#include <vector>
using namespace std;

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        res.push_back({});

        // 标准普通for遍历
        for (int k = 0; k < nums.size(); ++k) {
            int num = nums[k];
            int n = res.size();
            for (int i = 0; i < n; ++i) {
                vector<int> temp = res[i];
                temp.push_back(num);
                res.push_back(temp);
            }
        }
        return res;
    }
};

解法二(搜索)

cpp 复制代码
class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> path;
        backtrack(nums, 0, path, res);
        return res;
    }

    void backtrack(vector<int>& nums, int index, vector<int>& path, vector<vector<int>>& res) {
        res.push_back(path);
        for (int i = index; i < nums.size(); ++i) {
            path.push_back(nums[i]);
            backtrack(nums, i + 1, path, res);
            path.pop_back();
        }
    }
};
相关推荐
不是万能的豆学长3 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
时间静止不是简史3 小时前
生产事故排查:Redis 宕机导致补偿队列消费线程死亡,通话录音未上送业务平台
java·redis
gCode Teacher 格码致知4 小时前
Pandas教学-18:number与numeric的区别
python·pandas
2301_32241428046 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
梦想不只是梦与想7 小时前
Python 中subprocess 模块:执行外部命令
python·subprocess·调用外部命令
招聘风控观察7 小时前
招聘质量管理是什么?招聘质量的定义与评价口径完整解释
职场和发展
懂点Tech7 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
徐小夕8 小时前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
Robert--cao8 小时前
移动底盘与机械臂联合规划:开源算法与工程实现
算法
金銀銅鐵8 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程