7-15 输出全排列 (12分)(附详细讲解(不用递归的高效算法))

请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。
输入格式:
输入给出正整数n(<10)。
输出格式:
输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a1,a2,⋯,an排在序列b1,b2,⋯,bn之前,如果存在k使得a1=b1,⋯,ak=bk 并且 ak+1<bk+1。

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

分析
此题有两种分析法:第一种:将要n个要排列的整数看成一个整数,每次加9然后判断是否符合题目要求,成立就输出,例如:123到132,需要123加9;132到213,需要132加9个9……但是本人发现有很多无效数也要经过判断,因此最后一个测试点要超时(本地测试用时33秒),希望有大神能帮我解决这个问题,谢谢!
第二种:将n个数放入长度为n的数组,从左到右,数组中的第一个元素循环一次(循环条件范围是1到n),然后判断是否与前面的元素值一样,如果一样就再做一次循环,如果不一样就将下一个元素进行同样操作;如果超出循环条件范围,则先将当前位置下的元素值置为零,同时向左退一格,进行同样的操作……当最后一个元素经过处理后,就输出当前数组中的所有元素值。以输入样例为例,因为输入是3,所以先产生一个长度为3的数组,第零号元素先产生1,因为该元素是第一个元素,前面没有元素,且1在1到3之间,所以对下一个元素(即第1号元素)进行处理,第一号元素先产生1,因为1与第零号元素重复,所以在循环一次变为2,此时符合条件……当第2号元素产生3后,立即输出有元素(即123),因为第2号元素为最大,不能再循环了,所以向左退一格,此时该位置下元素变为3,符合条件……当321输出后,程序结束(此算法最后一个测试点用时500毫秒)。

#include<stdio.h>

int main(void)
{
	int a[9]={0};
	int i=0;
	int j=0;
	int k=0;
	int n=0;
	int temp=0;
	int count=0;
	int sum=1;

	scanf("%d",&n);
	
	for(i=1;i<=n;++i)
		sum*=i;			//模拟n!运算

	i=0;
	for(i=0;i<n;++i)
	{
up:
		for(temp=a[i]+1;temp<=n;)
		{
			for(k=0;k<i;++k)
				if(a[k]==temp)
					goto end;
			a[i]=temp;
			break;
		end:
			++temp;
		}
		if(temp>n)
		{
			a[i]=0;
			i=i-2;
		}	

		if(i==n-1)
		{
			for(j=0;j<n;++j)
				if(j==n-1)
					printf("%d\n",a[j]);
				else
					printf("%d",a[j]);
			++count;
			if(count==sum)
				break;
			goto up;
		}
	}
	return 0;
}

如果有误请告知作者,感激不尽!

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值