每日一小练——按字典顺序列出所有排列

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练!

题目:按字典顺序列出所有排列

内容:请写一个程序,用字典顺序列出n个元素的所有排列

这个问题有点小复杂,不是太好想,反正我是想了好久

看到这个题目我先是想到的就是递归因为这个题目就是用指针对高位选择,然后将指针传给临近的低位再选择。

不过仔细研究原来没这么简单。以n=4举例当处理以1开头的排列时1234到1432,但是在排列2开头的时候不太好建立统一的递归关系。(没办法太统一的递归方法中将后面的数字选出来),所以将第一位分类数字经行单独处理,其实第一位数字的选择也是又规律可循的。

1234  1432

2134  2431

3124  3421

4123  4321

12345  15432

21345  25431

....

可以看出1和2换时2都在最后一位,2和3换时,3在倒数第二位。。。就是你换第i个数时,就在倒数第i-1位。

然后我们再来处理除第一位的排列即从i,1,2,3,4,..i-1,i+i,..n(假设第一位是i)到i,n,...i+1,i-1,...3,2,1。的排列

其实这里也是有规律的,就是先从后向前查找第一个顺序相邻的位置然后交换,然后对交换后面的排列逆序。(其实这就是分解了我们人类排序的步骤,只是人的智能比较快,我们感受不到)。

比如 21354 从后向前第一个顺序相邻是35交换53为21534然后对后面逆序21435就是21354的后面一个数了。

当数列中没有顺序相邻了,我们的排列就结束了

如 4321,54321。

所以我们就可以按照这个规律来编写程序了。

#include <iostream>
using namespace std;

int set[1000];
bool signal = false;
int n;

int _tmain(int argc, _TCHAR* argv[])
{
	void changeFirst();
	cout << "请输入排列的集合的最大整数n:" << endl;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		set[i] = i + 1;
	}
	cout << "该集合的所有排列为:" << endl;
	changeFirst();
	getchar();
	getchar();
	return 0;
}

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

void reverse(int index_Start, int index_End)
{
	int length = index_End - index_Start;
	for (int i = 0; i <= length / 2; i++)
		swap(set[i + index_Start], set[length - i + index_Start]);

}

void permutationSet()
{
	for (int x = 0; x < n; x++)
		cout << set[x] << "  ";
	cout << endl;
	signal = false;
	int i, j, k;
	for (i = n - 2; i>0; i--)
	if (set[i]<set[i + 1])
	{
		j = i + 1;
		signal = true;
		break;
	}
	if (signal == false)
		return;
	for (k = n - 1; k>0; k--)
	if (set[k]>set[i])
		break;
	swap(set[i], set[k]);
	reverse(j, n - 1);
	permutationSet();
}

void changeFirst()
{
	int i = n - 1;
	while (i >= 0)
	{
		permutationSet();
		swap(set[0], set[i]);
		reverse(1, n - 1);
		i--;
	}
}

实验结果

欢迎大家加入每日一小练,嘿嘿!

每天练一练,日久见功夫,加油!

      -End-

参考文献:《c语言名题精选百则》

每日一小练——按字典顺序列出所有排列,布布扣,bubuko.com

时间: 2024-10-27 04:44:12

每日一小练——按字典顺序列出所有排列的相关文章

每日一小练——按字典顺序列出全部排列

上得厅堂,下得厨房,写得代码,翻得围墙.欢迎来到睿不可挡的每日一小练! 题目:按字典顺序列出全部排列 内容:请写一个程序,用字典顺序列出n个元素的全部排列 这个问题有点小复杂,不是太好想.反正我是想了好久. 看到这个题目我先是想到的就是递归由于这个题目就是用指针对高位选择,然后将指针传给临近的低位再选择. 只是细致研究原来没这么简单. 以n=4举例当处理以1开头的排列时1234到1432,可是在排列2开头的时候不太好建立统一的递归关系. (没办法太统一的递归方法中将后面的数字选出来),所以将第一

每日一小练——按字典顺序列出全部子集

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:按字典顺序列出全部子集 内容: 请写一个程序用字典顺序把一个{1,2,3,4,...,n}集合的全部子集找出来. 解答: 想必我就不用解释什么是字典顺序了,作为乘虚猿和攻城狮大家应该懂得,无论你懂不懂,反正我懂了! 事实上我们能够先列出一个实例,观察规律: 比如n=3 {1} {1,2} {1,2,3} {1,3} {2} {2,3} {3} 能够看出这种规律(假设你说我怎么没看出来,事实上你能够再多看一会!) 令一个

每日一小练——按字典顺序列出所有子集

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:按字典顺序列出所有子集 内容: 请写一个程序用字典顺序把一个{1,2,3,4,...,n}集合的所有子集找出来. 解答: 想必我就不用解释什么是字典顺序了,作为乘虚猿和攻城狮大家应该懂得,不管你懂不懂,反正我懂了! 其实我们可以先列出一个实例,观察规律: 例如n=3 {1} {1,2} {1,2,3} {1,3} {2} {2,3} {3} 可以看出这样的规律(如果你说我怎么没看出来,其实你可以再多看一会!) 令一个指

每日一小练——列出全部子集

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:列出全部子集 内容:写一个程序,列出{1,2,3,4,...,n}这个集合的全部子集,包含空集{ }. 解决问题的算法应该有非常多种,只是我发现了一种非常easy也非常好玩的方法,就是用二进制表示几何元素的方法 比方假设n是3,则子集有(不包含空集){1}{2}{3}{1,2}{1,3}{2,3}{1,2,3}就是1*{0,1}and2*{0,1}and3{0,1}每一个组合出现一次,所以也能够看成是{0,0,1}{0

每日一小练——列出所有子集

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:列出所有子集 内容:写一个程序,列出{1,2,3,4,...,n}这个集合的所有子集,包括空集{ }. 解决这个问题的算法应该有很多种,不过我发现了一种很简单也很好玩的方法,就是用二进制表示几何元素的方法 比如如果n是3,则子集有(不包括空集){1}{2}{3}{1,2}{1,3}{2,3}{1,2,3}就是1*{0,1}and2*{0,1}and3{0,1}每个组合出现一次,所以也可以看成是{0,0,1}{0,1,0

每日一小练——等值数目

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:等值数目 内容:已知两个整数数组f[]与g[],它们的元素都已经从小到大排列好,而且两个数组中的元素都各不相同.例如,f[]中有1,3,4,7,9,而g[]中有3,5,7,8,10.试编写程序算出这两个数组之间有多少组相同的元素.就上例而言,f[2]和g[1]为3是一组:f[4]和g[3]为8是一组.所以共有两组. 经过了前两天的编写,我觉得程序不具有代表性,所以我打算以后把核心算法的部分写出函数的形式,这样看起来更直

每日一小练——二项式系数加法解

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:二项式系数加法解 内容:请编写一个程序,仅仅用加法,求出n中取r个组合系数C(n,r),而且尽可能地使加法数目减少. 关于二项式:在数学里,二项式系数,或组合数,是定义为形如(1 + x)的二项式n次幂展开后x的系数(当中n为自然数,k为整数),通常记为.从定义可看出二项式系数的值为整数.这是来自百度的定义.我就不再赘余了. 关于二项式系数我们有一条性质使我们能够使用递归形式: C(n,r)=C(n,r-1)+C(n-

每日一小练——支配值数目

上得厅堂.下得厨房.写得代码.翻得围墙.欢迎来到睿不可挡的每日一小练! 题目:支配值数目 内容:已知f[]和g[]两个整数数组.元素都已经从小到大排列.试编敲代码算出f[]中每个元素比g[]中每个元素大的个数的总数. 换句话说.f[0]比g[]中多少个元素大.f[1]比g[]中多少个元素大.这些值得总和就是所要求的答案. 比如,假设f[]中有1,3,5,7,9,而g[]中有2,4,6,7,8,比g[0]大的有f[1]~f[4],比g[1]大的有f[2]~f[4],比g[2]大的有f[2]~f[4

每日一小练——数组的距离

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:数组的距离 内容:已知两个元素从小到大排列数组x[]和y[],请编写一个程序算出两个数组元素彼此之间差的绝度值中最小的一个 数,此值称作数组的距离. 例如:x[]有1,3,5,7,9   y[]有2,6,8  那么最短距离就是1,因为x[0]和y[0].x[1]和y[0].x[2]和y[1].x[3]和y[1]还有x[4]和 y[2]的距离都是1. 我的解法:上来没多想,打开vs2013就敲了起来,问题果然很简单,分分