题目
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
思路
回溯法,这里要注意如何保证一个排列里一个元素只能用一次:采用used数组来记录,path里已经有哪些元素,再遇到就跳过。排列问题中横向遍历时都要从0开始。
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
void backgrounding(vector<int>& nums,vector<bool>&used){
if(path.size()==nums.size()){
res.push_back(path);
return;
}
for(int i = 0;i<nums.size();i++){
if(used[i]==true) continue; //used[i]==true表示path里已经有了
path.push_back(nums[i]);
used[i]=true;
backgrounding(nums,used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<bool>used(nums.size(),false);//利用used数组来记录path中已经存在的元素,遇到就跳过
backgrounding(nums,used);
return res;
}
};
题目
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出: [[1,1,2], [1,2,1], [2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
思路
同样用回溯法,不过区别在于这里给的数组里有重复数字。所以要注意两点:
同层的话,要去重,遇到相同元素要跳过(值相同都不行);
同树枝的话,要避开path里已经记录的结点(可以值相同)。
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
void backgrounding(vector<int>& nums,vector<bool>& used){
if(path.size()==nums.size()){
res.push_back(path);
return;
}
for(int i = 0;i<nums.size();i++){
// used[i - 1] == true,说明同一树枝nums[i - 1]使用过
// used[i - 1] == false,说明同一树层nums[i - 1]使用过
// 如果同一树层nums[i - 1]使用过则直接跳过
//同层遇到相同元素就跳过
if( i>0 &&nums[i-1]==nums[i]&&used[i-1]==false)continue;
//避免同个树枝遇到已经遍历过的元素
if(used[i]==false){
used[i]=true;
path.push_back(nums[i]);
backgrounding(nums,used);
path.pop_back();
used[i]=false;
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool>used(nums.size(),false);
sort(nums.begin(),nums.end());//先排序再去重
backgrounding(nums,used);
return res;
}
};