题目
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
思考分析以及代码
这一题和前面的做过的两个题目有所关联:
leetcode 46. 全排列 思考分析
再加上leetcode 491. 递增子序列 思考分析类似的去重操作。
先画出解空间树的图:
红色部分才是真正意义上的去重:值相同的跳过。
蓝色部分指的是我们用过的元素不能再用了。在组合问题中由于for循环进入下一层是i+1,所以本身就将用过的元素排除了。然而在排列问题中,我们可能要用到序号靠前且没有使用过的元素,所以需要通过限制去除。
这里的“去重”我用到了两个数组:
vector<bool> used;
int usedArray[21]={0}; //这里使用数组来进行去重操作。
used存放的是树深度上的元素是否“用过”的信息,用过的元素将不会再用。
usedArray存放的是树这一层上的元素是否是重复的元素,重复的元素将不会再用。
所以used是全局变量,usedArray是本层的局部变量。
下面是代码:
class Solution {
public:vector<vector<int>> result;vector<int> res;vector<bool> used;void backtracking(vector<int>& nums){//如果res元素个数和nums一样多说明一个排列已经完成if(res.size() == nums.size()){result.push_back(res);return;}int usedArray[21]={0}; //这里使用数组来进行去重操作。for(int i=0;i<nums.size();i++){//used存放的是树深度上的元素是否“用过”的信息,用过的元素将不会再用。//usedArray存放的是树这一层上的元素是否是重复的元素,重复的元素将不会再用//元素可以是重复但没有用过。if(used[i] == false && usedArray[nums[i]+10] ==0){usedArray[nums[i]+10] =1;//处理结点;used[i]=true;res.push_back(nums[i]);//递归,探索下一层backtracking(nums); //递归//回溯,撤销处理结果res.pop_back();used[i]=false;}//如果这个元素已经用过了,不做处理}return;}vector<vector<int>> permuteUnique(vector<int>& nums) {result.clear();res.clear();//装载used数组for(int i=0;i<nums.size();i++) used.push_back(false);//开始回溯backtracking(nums);return result;}
};
剑指 Offer 38. 字符串的排列
https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/
这一题类似。