PTA数据结构 习题2.8 输出全排列 (20分)_WWIandMC的博客-程序员秘密

技术标签: PTA  

习题2.8 输出全排列 (20分)

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

输入格式:

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

输出格式:

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

输入样例:

3

输出样例:

123
132
213
231
312
321

全排列字典序算法

全排列生成算法
所谓字典序,就是将元素按照字典的顺序(a-z,1-9)进行排列。strcmp就是以字典序来比较字符串。

字典序算法步骤

设P是集合
{ 1 , 2 , . . . . . . n − 1 , n } \{1,2,......n-1,n\} { 1,2,......n1,n}
的一个全排列:P0P1…Pj-1PjPj+1…Pn

集合必须按照递增顺序排列好

  1. 从下标n开始递减,找出第一个比右边数字小的数字序号i
    P i < P i + 1 P_i<P_{i+1} Pi<Pi+1
  2. 在Pi右边的数字里,找到所有比Pj大的数字中最小的数字Pk,即
    k = min ⁡ { i ∣ P i > P j , i > j } k=\min\{i|P_i>P_j,i>j\} k=min{ iPi>Pj,i>j}
  3. 交换Pi,Pj
  4. i右边的序列Pi+1Pi+2…Pn逆置,变为PnPn-1…Pi+1

C++代码如下

#include <iostream>
#include <cstdio>

int
fact( int n );

void
dictSeq( int a[], int n );

void
reverse( int a[], int n, int j );

void
swaq( int &a, int &b );

void
print_array( int a[], int n );

int
main( void )
{
    
	int *a;
	int n;
	scanf("%d", &n);
	a = new int[n];
	for( int i = 0; i < n; i++ ){
    
		a[i] = i+1;
	}

	int total = fact(n);	//全排列个数等于n!
	print_array( a, n );	//初始序列算一种排列, 在交换之前单独输出

	for( int i = 1; i < total; i++ ){
    	//让dictSeq执行total-1次, 输出除初始序列之后的所有可能
		dictSeq( a, n );
	}

	return 0;
}

void
dictSeq( int a[], int n )
{
    
	int i;
	for( i = n-1; i > 0; i-- ){
    
		if( a[i-1] < a[i] ){
    
			i--;
			break;	
		}
	}
	
	int min_j = i + 1;
    int min = a[min_j];
	for( int j = min_j; j < n; j++ ){
    
		if( a[j] > a[i] && min > a[j] ){
    
			min = a[j];
			min_j = j;
		}
	}
	swaq( a[min_j], a[i] );
	reverse( a, n, i );
	print_array( a, n );
}

void
reverse( int a[], int n, int i )
{
    
	int left = i + 1, right = n - 1;
	while( left < right ){
    
		swaq( a[left++], a[right--]);
	}
}

int
fact( int n )
{
    
	int fact = 1;
	do{
    
		fact *= n--;
	}while( n > 0 );
	
	return fact;
}

void
swaq( int &a, int &b )
{
    
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void
print_array( int a[], int n )
{
    
	for( int i = 0; i < n; i++ ){
    
		printf("%d", a[i]);
	}
	printf("\n");
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/WWIandMC/article/details/107719933

智能推荐

Bert使用的激活函数:gelu---高斯误差线性单元_bert的激活函数_eunicechen的博客-程序员秘密

        Bert Transfromer结构中使用了这个激活函数---gelu(Gaussian error linear units,高斯误差线性单元),Gelu在论文中已经被验证,是一种高性能的神经网络激活函数,因为GELU的非线性变化是一种符合预期的随机正则变换方式(这句话,说实话,我翻译自原论文,具体怎么理解呢?我自己是如下理解的)。激活函数的作用:给网络模型加入非线性因子,这...

AndroidStudio 中如何导入和删除jar包_大道至簡的博客-程序员秘密

一、添加jar包的步骤:1、将jar包拷贝添加到 libs目录,libs文件夹在  app文件夹下(没有libs目录就自己手动创建个,app/libs )如图:2、然后再 右键单击项目,点击 Open Module Settings,在Dependencies中点“+”号,选择添加对应的jar文件,如图:这样就

DataGrid小技巧_JOHNCOOLS的博客-程序员秘密

//添加删除确认对话框:private void DataGrid1_ItemDataBound(   ){   switch(e.Item.ItemType)   {    case ListItemType.Item:    case ListItemType.AlternatingItem:    case ListItemType.EditItem:     ImageButt

Faster R-CNN源码阅读之四:Faster R-CNN/lib/rpn_msr/generate_anchors.py_子为空的博客-程序员秘密

一、介绍    本demo由Faster R-CNN官方提供,我只是在官方的代码上增加了注释,一方面方便我自己学习,另一方面贴出来和大家一起交流。    该文件中的函数主要都是与anchor的生成相关,即给定纵横比和尺寸等一定的参数,生成符合条件的若干个anchor(s)。 二、代码以及注释# -*- coding:utf-8 -*-# -----------------------...

[HDU2588]GCD(数论)_数论 gcd题目 hdu分类_Clove_unique的博客-程序员秘密

最典雅的友谊被矜持的水笔描画着,越描越淡。

随便推点

程序员修炼书籍_lm_y的博客-程序员秘密

计算机系统与网络《图灵的秘密》《计算机系统概论》《深入理解Linux内核》《深入Linux内核架构》《TCP/IP详解 卷1:协议》《Linux系统编程(第2版)》《Linux内核设计与实现(第3版)》《深入理解计算机系统(原书第2版)》《计算机程序的构造和解释(原书第2版)》《编码:隐匿在计算机软硬件背后的语言》《性能之颠:洞悉系统、企业与云计算》《UNIX网络编程 卷1:套接字联网API(第3...

KMP字符串匹配算法_pitt1997的博客-程序员秘密

最近学习在学习KMP算法时观看了视频之后理解的更加深刻,做一个笔记!视频地址:假设现在我们面临这样一个问题:有一个文本串T,和一个模式串P,现在要查找P在T中的位置,怎么查找呢?1.暴力匹配当a与b不能匹配上的时候,那么将P这个字符串整体往右移动一格移动之后继续从这个位置开始匹配,如果不能成功,那么继续右移一格:如果用暴力匹配的思路,并假设现在文本串T匹配到 i 位置,模式串P匹配...

nacos多服务全局配置_nacos全局配置_码上得天下的博客-程序员秘密

bootstrap-dev.yml配置如下:spring: profiles: active: dev cloud: #服务注册和发现 nacos: discovery: server-addr: 127.0.0.1:8848 service: ${spring.application.name} group: xx-service-${spring.profiles.active} config:

netty的编解码器介绍_惜暮的博客-程序员秘密

本blog主要介绍: 1. Codec 编解码器 2. Decoder 解码器 3. Encoder 编码器netty提供了强大的编解码器框架,使得我们编写自定义的编解码器很容易,也容易封装个重用。在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码。编解码器由两部分组成

9--黑马程序员--技术总结之多线程_我干阿衰的博客-程序员秘密

一.多线程的概念       以往开发的程序大多是单线程的,即一个程序只有一条从头至尾的执行线索。然而现实世界中的很多过程都具有多条线索同时动作的特性:例如,我们可以一边看电视,一边活动胳膊,如果不容许这样做,我们会感觉很难受。再如一个网络服务器可能需要同时处理多个客户机的请求等。        Java的一大特性点就是内置对多线程的支持。多线程是指同时存在几个执行体,按几条不同的执行

Valgrind内存泄漏工具的安装与使用 -- Linux_zerokkqq的博客-程序员秘密

Valgrind内存泄漏检测工具是一个十分便捷的工具,可以很快速的检测出所写程序是否存在内存泄漏现象,这对于C/C++程序员显得尤为重要,因为不论你有多牛逼,也难以保证自己不会忘写一个delete或者free。一:安装步骤首先下载一个Valgrind安装包。1.解压安装包 zip格式用 uzip Valgrind.xx.zip,解压完成之后进入该文件夹。2.运行./autogen.sh设置环境在执...