题目
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
- 输入: [1,2,3]
- 输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路
求全排列可以看成两步。第一步求出所有可能出现在第一个位置的字符,把第一个字符和后面所有的字符交换。第二步是固定第一个字符,求后面字符的全排列。此时仍然把后面的字符分两步处理,可以看出很明显是一个递归的步骤。
答案
参考笔记12。(想要避免冲突,需要添加set)。
class Solution {
public:
vector<vector<int>> ret; //结果数组
vector<vector<int>> permute(vector<int>& nums) {
findResult(nums,0); //x=0表示扫描到哪个位置
return ret;
}
//深搜回溯法
void findResult(vector<int>& nums,int x) {
if(x==nums.size()-1) {
ret.push_back(nums);
return;
}
for(int i=x;i<nums.size();i++) { //依次使用当前字符
swap(nums,i,x); //交换 将s[i]固定在x位
findResult(nums,x+1);
swap(nums,i,x); //恢复状态
}
}
void swap(vector<int>& nums,int i,int j){
int t=nums[i];
nums[i]=nums[j];
nums[j]=t;
}
};
#include <iostream>
#include <set>
#include <string>
#include <vector>
#include <stack>
#include <algorithm> //标准算法的头文件
using namespace std;
class Solution {
public:
vector<vector<int>> ret; //结果数组
vector<vector<int>> permute(vector<int>& nums) {
vector<int> item;
vector<int> used(nums.size(), 0); //空间换时间,记录当前数字是否用过
int usedNum = 0; //记录多少个数字用过
generateResult(nums, item, used, 0); //深搜递归回溯
return ret;
}
void generateResult(vector<int>& nums, vector<int>& item, vector<int>& used, int usedNum)
{
//递归结束条件
if (usedNum == nums.size()) {
ret.push_back(item);
return;
}
//依次使用当前数字
for (int i = 0; i < nums.size(); i++) {
//如果当前数字没有被使用,则使用
if (used[i] == 0) {
used[i] = 1; //标记为已使用
item.push_back(nums[i]);
//在当前位是当前数字的情况下,把所有的可能排列结果都找到并放入res;
generateResult(nums, item, used, usedNum + 1);
//当前位要换数字了,当前数字有可能出现在后面的位数里,所以开始回溯,清空状态量
used[i] = 0;
item.pop_back();
}
}
return;
}
};
void test01()
{
Solution solution;
//vector<int>v0 = { 1,2,2 };
vector<int> v0 = { 1,2,3 };
vector<vector<int>> ret = solution.permute(v0);
cout << ret.size() << endl;
//迭代器遍历
for (vector<vector<int>>::iterator it = ret.begin(); it != ret.end(); it++) {
for (vector<int>::iterator subit = (*it).begin(); subit != (*it).end(); subit++)
cout << (*subit) << "\t";
cout << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}