求一个数组或者string的全排列是很经典的问题。解决此类问题,首先在自己大脑思考,通常自己求一个数组的全排列会怎么求,比如arr[1, 2, 3],答案是:[1, 2, 3]、[1, 3, 2]、[2, 1, 3]、[2, 3, 1]、[3, 2, 1]、[3, 1, 2]。思路就是:从第一个字符开始和后面的字符进行交换,再从第二个字符开始和后面的进行交换,再第n-1和第n个交换。这样能够保证不会遗漏一些排列。
46. Permutations---利用回溯来做全排列
题目描述:
Given a collection of distinct numbers, return all possible permutations.
For example,
[1,2,3]
have the following permutations:
[ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
题目解析:
代码如下:
class Solution {
public:
// 使用递归回溯来解决此问题:此题没有重复字符,可以这样写
void permute(vector<int>& nums, int size, int start, vector<vector<int>> &out)
{
if(start == size-1)
{
out.push_back(nums);
return;
}
for(int i=start; i<size; ++i)
{
// 交换
int temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
// 递归求解
permute(nums, size, start+1, out);
// 回溯复原
temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
}
return;
}
vector<vector<int>> permute(vector<int>& nums)
{
vector<vector<int>> out;
if(nums.empty())
return out;
permute(nums, nums.size(), 0, out);
return out;
}
};
47. Permutations II---递归回溯
问题描述:
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2]
have the following unique permutations:
[ [1,1,2], [1,2,1], [2,1,1] ]
问题解析:
1. 此题也是求全排列。较上一题的不同点是此题的arr中可能出现重复数字。
2.因此此题需要在递归回溯时候做处理,首先,两个位置的数字相同就没有必要交换了,因为交换完结果是一样的,节省递归次数,直接跳过当前被交换位置就行。
3. 其次,在结果集中做个处理,使用set来存储结果集,避免出现重复结果。
代码如下:
class Solution {
public:
// 使用递归回溯来解决此问题
void permute(vector<int>& nums, int size, int start, set<vector<int>> &out)
{
if(start == size-1)
{
out.insert(nums);
return;
}
for(int i=start; i<size; ++i)
{
if(i!=start && nums[i] == nums[start])
continue;
int temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
permute(nums, size, start+1, out);
temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
}
return;
}
vector<vector<int>> permuteUnique(vector<int>& nums)
{
set<vector<int>> out;
permute(nums, nums.size(), 0, out);
return vector<vector<int>>(out.begin(), out.end());
}
};