P1706 全排列问题
P1706 全排列问题
题目
题目描述
按照字典序输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数n。
输出格式
由 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5 个场宽。
输入输出样例
输入 #1复制
3
输出 #1复制
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
说明/提示
1≤n≤9。
解题思路
方法1:
对一个数组中的每个元素进行交换实现全排列
但是顺序不是按字典序,不能AC该题目
把数组后面还未摆放的数,到摆放到k(当前要排的位置)的位置上(交换)
不用使用额外的判断数组进行是否使用过的判断
#include <bits/stdc++.h>
using namespace std;
int nums[9] = {1,2,3,4,5,6,7,8,9};
int n;
void f( int k ) {
//n个数排列完成
//输出结果
if ( k==n ) {
for( int i=0; i<n; i++ ) {
printf( "%5d", nums[i] );
}
cout << endl;
return ;
}
//k为当前要排的位置
//从k开始后面的数都还没有排列
//从k开始遍历后面的数
//逐个排列(交换)
for ( int i=k; i<n; i++ ) {
//交换
int t = nums[i];
nums[i] = nums[k];
nums[k] = t;
//递归
f( k+1 );
//恢复状态
t = nums[i];
nums[i] = nums[k];
nums[k] = t;
}
}
int main() {
cin >> n;
f(0);
}
方法2:
需要额外的数组进行判断数字是否使用过
该方法实现的全排列按照字典序
每次都重新遍历一次数组,查看那个数字未使用就放到当前要排列的位置,同时标记
#include <bits/stdc++.h>
using namespace std;
int nums[9] = {1,2,3,4,5,6,7,8,9};
int n;
//判断标记数组
int flag[9] = {0,0,0,0,0,0,0,0,0};
//答案数组
int res[9] = {0,0,0,0,0,0,0,0,0};
void f2( int len ) {
//排序完成输出
if ( len==n ) {
for( int i=0; i<n; i++ ) {
printf( "%5d", res[i] );
}
cout << endl;
return ;
}
//从头开始检查那些元素未使用
for ( int i=0; i<n; i++ ) {
if ( flag[i]==1 ) { //使用过跳过
continue;
}
//未使用的排到该位置
res[len] = nums[i];
flag[i] = 1;//标记
f2( len+1 );
flag[i] = 0;//恢复
}
}
int main() {
cin >> n;
f2(0);
}
版权声明:本文为m0_53022813原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。