Peck Chen

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

求当前排列的下K个排列:

(1):当当前排列为逆序排列时(最后一个排列), 下一个排列为:1 2 3 4 ....N

(2):下K次排列, 每次改变一次排列, 要考虑(1)

(3):要得到下一次排列, 从An开始, 当Ai > Ai-1时, 将Ai ~An从小到大排序, 在Ai ~ An中找出第一个大于Ai-1的数,

交换, 再将Ai ~ An从小到大排序就得到相应的下一个排列。

 

用include <algorithm>中的next_permutation(), 也可以很快求出排列

 

交换时用第0号元素当中间变量, 实现交换, 不知怎么的当时交换的方式乱七八糟的, 就错了几次....唉

 

Accepted  144K  547MS  C  2115B  2010-11-25 19:53:32

 

代码
#include <stdio.h>
#include
<stdlib.h>

/* 判断是否是最后一个排列 */
char is_last_per(int *num, int n)
{
int i;

for (i = 1; i < n; i++)
{
if (num[i] > num[i+1])
{
continue;
}
else
{
return '0';
}
}

return '1';
}

/* 快速排序 */
void quick_sort(int *num, int *begin , int *end)
{
int *i, *j;

if (end - begin <= 1)
{
return;
}

i
= begin;
j
= end - 1;
num[
0] = *begin;
while (i < j)
{
while (i < j && num[0] <= *j)
{
j
--;
}
if (i < j)
{
*i = *j;
i
++;
}
while (i < j && num[0] >= *i)
{
i
++;
}
if (i < j)
{
*j = *i;
j
--;
}
}
*j = num[0];

quick_sort(num, begin, j);
/* 左边 */
quick_sort(num, j
+ 1, end); /* 右边 */
}

/* 输出 */
void print(int *num, int n)
{
int i;

for (i = 1; i <= n; i++)
{
printf(
"%d", num[i]);
if (i != n)
{
putchar(
' ');
}
else
{
putchar(
'\n');
}
}
}

/* 设置下一个排列 */
void set_per(int *num, int n)
{
int i, j;
char is_last; /* 判断是否是最后一个排列 */

is_last
= is_last_per(num, n);
if (is_last == '1') /* 不是最后一个排列 */
{
for (i = 1; i <= n; i++)
{
num[i]
= i;
}
}
else
{
for (i = n; i > 1; i--)
{
if (num[i] > num[i-1])
{
quick_sort(num,
&num[i], &num[n+1]); /* 一共两次排序 */
for (j = i; j <= n; j++)
{
if (num[i-1] > num[j])
{
continue;
}
else /* 交换 */
{
num[
0] = num[i-1];
num[i
-1] = num[j];
num[j]
= num[0];
break;
}
}
quick_sort(num,
&num[i], &num[n+1]); /* 一共两次排序 */
return;
}
else
{
continue;
}
}
}
}

/* 第k个排列 */
void k_permutation(int num[], int n, int k)
{
while ( k-- ) /* k次排列, 每次改变一次 */
{
set_per(num, n);
/* 设置下一个排列 */
}
}

int main()
{
int cas, n, k, i, *num;

scanf(
"%d", &cas);
while ( cas-- )
{
scanf(
"%d%d", &n, &k);
if ((num=(int *) calloc (n + 1, sizeof(int))) == NULL)
{
printf(
"空间分配失败!\n");
exit(
-1);
}

for (i = 1; i <= n; i++)
{
scanf(
"%d", &num[i]);
}

k_permutation(num, n, k);
/* 下k个排列后 */
print(num, n);

free( num );
num
= NULL;
}
}

 

 

/*问题描述大家知道,给出正整数n,则1 到n 这n 个数可以构成n!种排列,把这些排列按照从小到大的顺序

(字典顺序)列出,如n=3 时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1六个排列。给出某个排列,

求出这个排列的下k 个排列,如果遇到最后一个排列,则下1 排列为第1 个排列,即排列1 2 3…n。

比如:n = 3,k=2 给出排列2 3 1,则它的下1 个排列为3 1 2,下2 个排列为3 2 1,因此答案为3 2 1。
输入数据第一行是一个正整数m,表示测试数据的个数,下面是m 组测试数据,每组测试数据第一行是2 个正整数n

( 1 <= n < 1024 )和k(1<=k<=64),第二行有n 个正整数,是1,2 … n的一个排列。
输出要求对于每组输入数据,输出一行,n 个数,中间用空格隔开,表示输入排列的下k 个排列。
输入样例33 12 3 13 13 2 110 21 2 3 4 5 6 7 8 9 10
输出样例3 1 21 2 31 2 3 4 5 6 7 9 8 10*/

posted on 2010-11-25 20:07  PeckChen  阅读(919)  评论(0编辑  收藏  举报