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. 结束

相关推荐
tinker在coding1 分钟前
Coding Caprice - Linked-List 1
算法·leetcode
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子5 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡5 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin5 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码6 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7246 小时前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活6 小时前
理解支持向量机
算法·机器学习·支持向量机