求一個數組或者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());
}
};