200.回溯算法:子集||(力扣)

cpp 复制代码
class Solution {
public:
    vector<int> res;                // 当前子集
    vector<vector<int>> result;     // 存储所有子集

    void backtracing(vector<int>& nums, int index, vector<bool>& used) {
        result.push_back(res);      // 将当前子集加入结果

        for (int i = index; i < nums.size(); i++) {
            // 跳过重复元素
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1]==false) {
                continue;
            }

            res.push_back(nums[i]);  // 将当前元素加入子集
            used[i] = true;          // 标记当前元素已使用

            backtracing(nums, i + 1, used); // 递归生成后续子集

            used[i] = false;         // 取消标记,回溯
            res.pop_back();          // 从子集中移除当前元素,回溯
        }
    }

    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<bool> used(nums.size(), false);  // 标记数组元素是否被使用
        sort(nums.begin(), nums.end());         // 排序数组以便于去重
        backtracing(nums, 0, used);             // 调用回溯函数开始生成子集
        return result;                          // 返回所有生成的子集
    }
};

主函数调用

  1. subsetsWithDup 函数 :
    • 输入 nums = {1, 2, 2}
    • 初始化 used = {false, false, false}
    • nums 进行排序(尽管已经排好序了),结果 nums = {1, 2, 2}
    • 调用 backtracing(nums, 0, used)

回溯函数执行

  1. 第一次调用 backtracing(nums, 0, used):

    • index = 0
    • 当前子集 res = {}
    • 当前结果 result = {``{}}

    循环1(i = 0):

    • nums[0] = 1 未使用
    • res.push_back(1) -> res = {1}
    • used[0] = true
    • 调用 backtracing(nums, 1, used)
  2. 第二次调用 backtracing(nums, 1, used):

    • index = 1
    • 当前子集 res = {1}
    • 当前结果 result = {``{}, {1}}

    循环1(i = 1):

    • nums[1] = 2 未使用
    • res.push_back(2) -> res = {1, 2}
    • used[1] = true
    • 调用 backtracing(nums, 2, used)
  3. 第三次调用 backtracing(nums, 2, used):

    • index = 2
    • 当前子集 res = {1, 2}
    • 当前结果 result = {``{}, {1}, {1, 2}}

    循环1(i = 2):

    • nums[2] = 2 未使用
    • res.push_back(2) -> res = {1, 2, 2}
    • used[2] = true
    • 调用 backtracing(nums, 3, used)
  4. 第四次调用 backtracing(nums, 3, used):

    • index = 3
    • 当前子集 res = {1, 2, 2}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}}
    • 结束条件 index >= nums.size() 达成,返回上一层

    回溯:

    • res.pop_back() -> res = {1, 2}
    • used[2] = false
    • 返回上一层
  5. 回到第三次调用 backtracing(nums, 2, used):

    • 当前子集 res = {1, 2}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}}

    回溯:

    • res.pop_back() -> res = {1}
    • used[1] = false

    循环2(i = 2):

    • nums[2] = 2 未使用,且 nums[2] == nums[1],但 used[1] == false,跳过
    • 返回上一层
  6. 回到第二次调用 backtracing(nums, 1, used):

    • 当前子集 res = {1}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}}

    回溯:

    • res.pop_back() -> res = {}
    • used[0] = false

    循环2(i = 1):

    • nums[1] = 2 未使用
    • res.push_back(2) -> res = {2}
    • used[1] = true
    • 调用 backtracing(nums, 2, used)
  7. 第五次调用 backtracing(nums, 2, used):

    • index = 2
    • 当前子集 res = {2}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}, {2}}

    循环1(i = 2):

    • nums[2] = 2 未使用
    • res.push_back(2) -> res = {2, 2}
    • used[2] = true
    • 调用 backtracing(nums, 3, used)
  8. 第六次调用 backtracing(nums, 3, used):

    • index = 3
    • 当前子集 res = {2, 2}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}, {2}, {2, 2}}
    • 结束条件 index >= nums.size() 达成,返回上一层

    回溯:

    • res.pop_back() -> res = {2}
    • used[2] = false
    • 返回上一层
  9. 回到第五次调用 backtracing(nums, 2, used):

    • 当前子集 res = {2}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}, {2}, {2, 2}}

    回溯:

    • res.pop_back() -> res = {}
    • used[1] = false
    • 返回上一层
  10. 回到第一次调用 backtracing(nums, 0, used):

    • 当前子集 res = {}
    • 当前结果 result = {``{}, {1}, {1, 2}, {1, 2, 2}, {2}, {2, 2}}

    循环3(i = 2):

    • nums[2] = 2 未使用,且 nums[2] == nums[1],但 used[1] == false,跳过
  11. 结束

相关推荐
じ☆冷颜〃5 小时前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
数据大魔方5 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
POLITE35 小时前
Leetcode 23. 合并 K 个升序链表 (Day 12)
算法·leetcode·链表
楚来客5 小时前
AI基础概念之八:Transformer算法通俗解析
人工智能·算法·transformer
Echo_NGC22376 小时前
【神经视频编解码NVC】传统神经视频编解码完全指南:从零读懂 AI 视频压缩的基石
人工智能·深度学习·算法·机器学习·视频编解码
会员果汁6 小时前
leetcode-动态规划-买卖股票
算法·leetcode·动态规划
橘颂TA6 小时前
【剑斩OFFER】算法的暴力美学——二进制求和
算法·leetcode·哈希算法·散列表·结构与算法
地平线开发者8 小时前
征程 6 | cgroup sample
算法·自动驾驶
尋有緣8 小时前
力扣1355-活动参与者
大数据·数据库·leetcode·oracle·数据库开发