題目描述:給定一個沒有重複數字的序列,返回其全部可能的全排列。
示例:
輸入: [1,2,3]
輸出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:遞歸
假設數據規模爲n(這裏表示數組的長度)
- n = 1 :只有自身一種序列
- n = 2 :1.第一種序列就是自身 2.兩數交換位置,造成第二種序列
- n = 3:爲了縮小數據規模,能夠拆分紅1 + 2的狀況。即:[1 + 2, 3] [2 + 1, 3] [3 + 1 ,2]。每一個數字都有一次機會放在首位,剩下的兩個數字就變成n = 2的狀況了。
- n > 3:參考n = 3的狀況,利用遞歸逐級縮小數據規模。
按照上述思路,翻譯成C++代碼以下:
/**
* @param arr 輸入的數組
* @param start 參與排列的起始位置
* @param end 參與排列的結束位置
*/
void Permatation(int arr[], int start, int end)
{
// 數據規模縮小到1,直接輸出
if (start == end)
{
for (int i = 0; i <= end; ++i)
{
if (i != 0)
{
std::cout << " ";
}
std::cout << arr[i];
}
std::cout << std::endl;
}
// 數據規模縮小到2,交換位置輸出兩種狀況
else if (start + 1 == end)
{
Permatation(arr, start + 1, end); // 輸出第一種狀況
std::swap(arr[start], arr[end]); // 交換位置
Permatation(arr, start + 1, end); // 輸出第二種狀況
std::swap(arr[start], arr[end]); // 復原交換,保證不影響後續操做
}
// 數據規模大於2
else
{
Permatation(arr, start + 1, end); // 首位數字不變,縮小規模
for (int i = start + 1; i <= end; ++i)
{
std::swap(arr[start], arr[i]); // 從start + 1開始,每一個數字都有一次機會放在首位
Permatation(arr, start + 1, end); // 縮小規模
std::swap(arr[start], arr[i]); // 複本來次交換,保證不影響後續操做
}
}
}
int main()
{
int arr[] = { 1, 2, 3};
Permatation(arr, 0, sizeof(arr) / sizeof(arr[0]) - 1);
std::cin.get();
return 0;
}
輸出:
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
通過分析,n = 2 和 n > 2 時候的處理過程十分類似,能夠合併在一塊兒。
AC代碼,執行用時:8 ms
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> ret;
gen_perm(nums, 0, nums.size() - 1, ret);
return ret;
}
void gen_perm(vector<int>& nums, int start, int end, vector<vector<int>> & ret)
{
if(start == end)
{
ret.push_back(nums);
}
else
{
for(int i = start; i <= end; ++i)
{
swap(nums[start], nums[i]);
gen_perm(nums, start + 1, end, ret);
swap(nums[start], nums[i]);
}
}
}
};