一、 题目展示
这是一道全排列的题,而全排列这个知识点是很重要的,小伙伴们一定要掌握哦!接下来我会用两种方法对这个问题经行解答。
二、解决方法
方法一:C++(自带的全排列函数next_permumtation())
我们都知道C++的函数库是那么的强大,在这里面自带的全排列函数next_permumtation()就可以很好的解决我们的这个问题,在这里博主只是提供解法,至于这个函数的使用方法很简单,网上也有很多这方面的知识,不懂的小伙伴可以自己去了解了解哦!
注意:对于这道题而言,我们在使用这个函数时,要首先对给我们的数组排序,让它从小到大的排序后再使用该函数,开始博主就是忘记这一条件才使得所得到的答案不完善。
下面是博主自己的写的代码,小伙伴可以看看(有博主自己的注释):
class Solution {
public:
vector<vector<int>>arr;//建立动态数组保存结果
vector<vector<int>> permute(vector<int>& nums) {
sort(nums.begin(),nums.end());对原数组经行排序
do
{
vector<int>a;//建立一个数组保存每一次排序的值
for(int i=0;i<nums.size();i++)
{
a.push_back(nums[i]);
}
arr.push_back(a);
}while(next_permutation(nums.begin(),nums.end()));//使用该函数的条件
return arr;//返回最终的答案
}
};
方法二:搜索+回溯算法
对于上一种方法而言更像一种模板,但是博主觉得搜索+回溯的方法虽然有点抽象,但是更适合这类问题的求解:
其实,对于这种组合问题,用回溯算法是刚刚好的,掌握这种方法以后对于类似的问题就会迎刃而解了。
我们以数组【1,2,3】为例,我们用将其展开其实是一颗满二叉树,为了大家更好的理解博主自己画了一个图(画的太不好了,希望各位小伙伴能看懂),如图所示:
我们不难发现,对于这棵满二叉树,我们将每一次搜索的结点的组合,就是我们的一次排序结果,就刚好形成上述的六种结果。我们知道了这棵是怎么样的后,就可以开始写我们的代码了:
首相:分别定义动态数组arr和a分别保存最终结果,和每一次搜索的结果。
①结束的边界:当我们a数组的长度与所给的数组nums的长度相同时,用arr保存a的值
if(a.size()==nums.size())
{
arr.push_back(a);
return ;
}
②:深搜函数dfs()参数的定义,除了题目给出的nums数组外,我们还要定义一个bool类型的函数参数b数组,来把我们每次已经访问过的数进行标记,防止出现重复的数。
有了以上的两个步骤,我们就可以写自己的代码了。
代码展示(有博主自己的注释):
class Solution{
public:
vector<vector<int>>arr;
vector<int>a;
vector<vector<int>> permute(vector<int>& nums){
arr.clear();//清空动态数组
a.clear();
vector<bool>b(nums.size(),false);//初始化
dfs(nums,b);
return arr;//返回最终值
}
void dfs(vector<int>& nums,vector<bool>& b)
{
if(a.size()==nums.size())//边界的条件
{
arr.push_back(a);
return ;
}
for(int i=0;i<nums.size();i++)
{
if(b[i]==true)//如果已经访问过,直接跳过
continue;
b[i]=true;//进行标记
a.push_back(nums[i]);//存入a数组
dfs(nums,b);//递归
a.pop_back();//进行回溯操作
b[i]=false;
}
}
};
总结:
好吧,到这我们这道题就算是解决了,如果有错误与不妥之处,希望大佬指正,或者有不懂的小伙伴可以在评论区留言哦,博主一定会耐心解答滴!还有博主想说,我们在刷题的时候,不要只是为了刷题而刷题,我们更应该去寻找问题的多重解,理解每种解法的核心思想,这种思维才是我们最需要的!还有如果觉得博主的这篇题解还不错的话,友友们给博主点个赞叭,谢谢啦!博主会继续努力的,大家也要加油哦,冲冲冲!!!