class Solution { public: vector<int> res; // 存储当前排列 vector<vector<int>> result; // 存储所有排列 // 回溯函数,用于生成排列 void backtracing(vector<int>& nums, vector<bool>& used) { // 如果当前排列的长度等于 nums 的长度,说明找到一个完整的排列 if (res.size() == nums.size()) { result.push_back(res); // 将当前排列加入结果集 return; } // 遍历每一个数字,尝试将其加入当前排列 for (int i = 0; i < nums.size(); i++) { // 如果当前数字和前一个数字相同,且前一个数字未被使用过,则跳过,避免重复排列 if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { continue; } // 如果当前数字未被使用过 if (used[i] == false) { used[i] = true; // 标记当前数字已使用 res.push_back(nums[i]); // 将当前数字加入当前排列 backtracing(nums, used); // 递归处理剩余的数字 res.pop_back(); // 回溯,移除最后一个数字 used[i] = false; // 标记当前数字未使用 } } } // 主函数,生成所有唯一排列 vector<vector<int>> permuteUnique(vector<int>& nums) { vector<bool> used(nums.size(), false); // 初始化一个布尔向量用于标记数字是否已被使用 sort(nums.begin(), nums.end()); // 排序数组,便于处理重复元素 backtracing(nums, used); // 调用回溯函数,开始生成排列 return result; // 返回所有的排列组合 } };
递归与回溯:
- 使用递归函数
backtracing
来生成所有的排列组合。- 每次选择一个元素加入当前排列
res
中,然后递归处理剩余的元素。- 递归结束后,回退到上一步,移除最后加入的元素,继续尝试其他可能的选择。
剪枝:
- 通过
used
数组来避免重复使用已经加入到当前排列中的元素。- 通过排序数组以及检查相邻元素来避免生成重复排列:
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false)
。这条语句确保了对于重复元素,在一个排列中只考虑第一个出现的元素,从而避免重复排列。状态变量:
res
:用于存储当前正在构建的排列。result
:用于存储所有找到的排列。used
:一个布尔数组,用于标记某个元素是否已经在当前排列中使用过,避免重复使用。
202.回溯算法:全排列||(力扣)
最新推荐文章于 2024-06-27 05:31:24 发布