题目描述
生成由1至n个数的全排列。
输入
输入包含多组样例,每组样例输入一个整数n(1≤n≤9)。
输出
按照字典序反序输出,每个数值之间用空格隔开。每个排列单独占一行。
我做的该题,要求逆字典序就改了一下大于小于号
字典序
#include <stdio.h>
#include <stdlib.h>
int num[10];
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)b - *(int*)a );
}
int main(){
int n,i,a,b,t;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++) num[i]=n-i;
while(1){
for(i=0;i<n-1;i++) printf("%d ",num[i]);
printf("%d\n",num[n-1]);
a=-1;
for(i=n-1;i>0;i--)
if(num[i-1]>num[i]) {a=i-1;break;}
if(a==-1)break;
for(i=n-1;i>0;i--)
if(num[i]<num[a]) {b=i;break;}
t=num[a];num[a]=num[b];num[b]=t;
qsort(num+a+1,n-a-1,sizeof(int),cmpfunc);
}
}
}
逆字典序
DFS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int num[10];
int visited[10];
int n,t;
void dfs(int x){
if(t==n) {int j;for(j=0;j<n-1;j++) printf("%d ",num[j]);
printf("%d\n",num[n-1]);}
int i;
for(i=n-1;i>=0;i--)
{
if(!visited[i])
{visited[i]=1;
num[t++]=i+1;
dfs(i+1);
visited[i]=0;
t--;
}
}
}
int main(){
int i;
while(scanf("%d",&n)!=EOF){
memset(visited,0,sizeof(visited));
t=0;dfs(0);
}
}
非字典序
分冶
#include <stdio.h>
int num[10],n;
void Swap(int &a, int &b){
int temp = a;
a = b;
b = temp;
}
void perm(int k,int m){
if(k==m){
int j;for(j=0;j<n;j++) printf("%d ",num[j]);
printf("\n");
}else{
int i;
for(i=k;i<=m;i++){
Swap(num[k],num[i]);
perm(k+1,m);//固定位置
Swap(num[k],num[i]);
}
}
}
int main(){
int i;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++)
num[i]=i+1;
perm(0,n-1);
}
}
有重复数字
class Solution {
public:
vector<vector<int> > res;
vector<vector<int> > permuteUnique(vector<int> &num) {
sort(num.begin(),num.end());
perm(num,0,num.size());
return res;
}
void swap(int &a,int &b){
int temp=a;
a=b;
b=temp;
}
void perm(vector<int> num,int k,int m){
if(k==m){
res.push_back(num); return;
}else{
for(int i=k;i<m;i++){
if(!isSwap(num,k,i)) continue;
swap(num[i],num[k]);
perm(num,k+1,m);
swap(num[i],num[k]);}
}
}
bool isSwap(vector<int > num,int begin,int end){
for(int i=begin;i<end;i++)
if(num[end]==num[i]) return false;
return true;
}
};
是否可以交换,就是看是交换的元素和前面的那些元素有没有重复