乱序全排列 简单回溯算法
力扣46 例题
给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。
例:
输入:[1,3,4]
返回:[[1,3,4],[1,4,3],[3,1,4],[3,4,1],[4,1,3],[4,3,1]]
题解
了解了基本的全排列问题以后(见顺序全排列),了解了基本的回溯算法的思路,那么这道题有了一种新的回溯的思路;
同样的是三个数字,给定了一个数组nums[],但是数组里面的数字并不按照顺序排列,而是任意的三个数字;
基本思路不变,但是我们这次用一个新的思路;
例如[1,2,3]
,绑定第一个数字1之后,我们只需要交换nums[1]
和nums[2]
的顺序,就可以得到一个新的数列,也就是[1,3,2]
,同样的思路,绑定了2以后,因为2是nums[1]
,所以我们只需要交换nums[0]
和nums[2]
的顺序,就可以的到一个新的序列[2,1,3]
和[2,3,1]
,交换顺序就等价于之前讲过的使用数据,交换回来就相当于重置数据;
那么根据上面的思路,就可以写出代码:
#include <iostream>
#include <vector>
using namespace std;
void backk(vector<vector<int> >& res,vector<int>& output,int first,int len){
if(first == len){ // 出口 如果已经交换到最后一个了 就可以输出
res.push_back(output); // output加入到res容器中
return ;
}
for(int i = first;i < len;i++){
swap(output[i],output[first]); // 绑定第一个数字之后,进入循环开始交换另外两个数
backk(res,output,first + 1,len); // 进入递归
swap(output[i],output[first]); // 交换完成后,再次交换以重置数据,也就是回溯中的退回
}
}
int main(){
vector<int> nums;
vector<vector<int> > res;
int n;
int num;
cin >> n;
for(int i = 0;i < n;i++){ // 依次输入准备全排列的数字
cin >> num;
nums.push_back(num);
}
backk(res,nums,0,(int)nums.size());
for(int i = 0;i < res.size();i++){ // 输出二维容器
for(int j = 0;j< res[i].size();j++){
cout << res[i][j] << " ";
}
cout << endl;
}
return 0;
}
/*力扣返回值
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int> > res;
backk(res,nums,0,(int)nums.size());
return res;
}
*/
解释①
加入数据的时候使用 push_back()需要先构造临时对象,再将这个对象拷贝到容器的末尾,而emplace_back()则直接在容器的末尾构造对象,这样就省去了拷贝的过程。
尾言
感谢您的阅读!
如果文章有错误请留言指出,谢谢!