7-2 输出全排列 (20 分)

11 篇文章 1 订阅

请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。

输入格式:
输入给出正整数n(<10)。

输出格式:
输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a1​​ ,a​2,⋯,a​n 排在序列b​1,b​2​​ ,⋯,b​n之前,如果存在k使得a​1​​ =b​1​​ ⋯,a
​k=bk并且 a​k+1<b​k+1。

输入样例:
3
输出样例:
123
132
213
231
312
321

方法一:(回溯)

//思路:借鉴第一题,将全排列抽象成一个数(n个数的和)的分解,加上判断函数剪去不必要的部分即可
#include<stdio.h>
int m;
int cnt=0;
int zz[35];

void print()
{
    int i;
    for(i=0;i<m;i++)
    {

            printf("%d",zz[i]);
    }
}
int check(int i,int l)
{
    int n;
    int w;
    for(w=0;w<l;w++)
    {
        if(zz[w]==i)
            return 0;

    }
    return 1;

}
int F(int n,int k,int l)
{
    int i;

    if(n==0)
    {
        print();
        printf("\n");
        return 0;
    }
    for(i=1;i<=m;i++)
    {
        if(check(i,l))
        {
            zz[l]=i;
            F(n-i,i,l+1);

        }

    }

}
int add(int n)
{
    int i;
    int sum=0;
    for(i=0;i<=n;i++)
    {
        sum+=i;
    }
    return sum;
}
int main()
{

    int n;
    int sum;
    scanf("%d",&n);
    sum=add(n);
    m=n;
    F(sum,0,0);
    return 0;
}

方法二:

//思路:采用递归思想,将问题分解,每次移动都会固定一些数字是不动的,如123,132...  其中 1 就是不动的那个数。
//每个小问题的解决通过将数组元素“拿”到离他最近的不动的元素之后,即将其取出,目标位置及以后的数后移,将拿出来的数填充上
//复原方法相反

#include <iostream>
#include <stdio.h>
using namespace std;
void Print(int *a,int t);
void Insert(int* &a,int t,int f)   //将t位置的数拿到f处,f处及以后向后移
{
    int i;
    int temp;
    temp=*(a+t);
    for(i=t;i>f;i--)
    {
        *(a+i)=*(a+i-1);
    }
    *(a+f)=temp;
 
}
void Move(int* &a,int t,int f)  //将上面那个函数的改变还原
{
    int i;
    int temp=a[t];
    for(i=t;i<f;i++)
    {
        a[i]=a[i+1];

    }
    a[f]=temp;
 

}
void swap(int &a,int &b){
    int temp=a;
    a=b;
    b=temp;
}
void Print(int* a,int low)                  //输出函数独立出来,没别的,主要方便调试
{

    for(int i=0;i<=low;i++)
            cout<<a[i];
        cout<<endl;
}
void perm(int a[],int low,int high){
    if(low==high){   //当low==high时,此时list就是其中一个排列,输出list
        Print(a,low);
    }else{
        for(int i=low;i<=high;i++){         //每个元素插入到最近的一个不动的数字后
    
            Insert(a,i,low);                 //将元素插入,
    
            perm(a,low+1,high); //交换后,得到子序列,用函数perm得到子序列的全排列
           
            Move(a,low,i);            //将数组还原到上一个改变之前

        }
    }
}
int main()
{int n;
scanf("%d",&n);
int *a;
a=new int[20];                   //为了以后数组够用,不会出现溢出现象,特意将数组开大
for(int i=0;i<n;i++)
{
    a[i]=i+1;
}
perm(a,0,n-1);
return 0;
}
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值