问题 A: 【递归入门】全排列
时间限制: 1 Sec 内存限制: 128 MB
提交: 213 解决: 134
题目描述
排列与组合是常用的数学方法。
先给一个正整数 ( 1 < = n < = 10 )
例如n=3,所有组合,并且按字典序输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
输入
输入一个整数n( 1<=n<=10)
输出
输出所有全排列
每个全排列一行,相邻两个数用空格隔开(最后一个数后面没有空格)
样例输入
3
样例输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
经验总结
第一次自己写超简单的全排列。。。然而还是一脸懵逼。。。想了两个小时都没搞懂。。。果然是个菜鸡T - T 后来参考了一下别人的正确代码,对比自己的,就发现了问题。。。问题很简单,全排列是要保存一个结果输出的,而我只是在每层递归里进行输出,而且位置还不对。。。
所以,第一次接触还是深有感触,递归这个东西,思路一定要清晰,抓住两点,1.跳出条件 也就是满足何种条件时不继续进行递归 2.递归嵌套的方式,即递归往下的分岔口应该长什么样。。当然,如果有数据需要保存,就需要考虑在哪里保存数据以及用什么数据结构保存,这次纯属自己菜= =,相信自己会慢慢变强!!
递归代码
#include <cstdio>
int n;
bool flag[20]={false};
int ans[20];
void combine(int count)
{
if(count==n)
{
for(int i=0;i<n;i++)
{
printf("%d ",ans[i]);
}
printf("\n");
return ;
}
for(int i=0;i<n;i++)
{
if(flag[i]==false)
{
ans[count]=i+1;
flag[i]=true;
combine(count+1);
flag[i]=false;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
int count=0;
combine(count);
}
return 0;
}
非递归代码
递归与非递归最好都要会,这样才能真正的理解算法的运行过程,学习递归最直接的方法就是学会比较递归与非递归之间的相同点与不同点~~
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;
vector<int> answer;
stack<int> process;
bool flag[20]={false};
int n;
void combine()
{
process.push(1);
answer.push_back(1);
flag[1]=true;
int visit;
bool pop=false;
while(!process.empty())
{
if(answer.size()==n)
{
for(int i=0;i<n;i++)
{
printf("%d ",answer[i]);
}
printf("\n");
pop=true;
}
visit=-1;
for(int i=1;i<=n;i++)
{
if(flag[i]==false)
{
visit=i;
break;
}
}
if(visit==-1)
{
flag[process.top()]=false;
process.pop();
answer.pop_back();
pop=true;
continue;
}
if(pop)
{
bool search=false;
for(int i=process.top()+1;i<=n;i++)
{
if(flag[i]==false)
{
search=true;
visit=i;
break;
}
}
flag[process.top()]=false;
process.pop();
answer.pop_back();
if(search==false)
{
pop=true;
continue;
}
else
{
pop=false;
}
}
if(visit!=-1)
{
flag[visit]=true;
process.push(visit);
answer.push_back(visit);
}
}
}
int main()
{
while(~scanf("%d",&n))
{
combine();
}
return 0;
}