排列序列

/*
给出集合 [1,2,3,...,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。

 

示例 1:

输入:n = 3, k = 3
输出:"213"
示例 2:

输入:n = 4, k = 9
输出:"2314"
示例 3:

输入:n = 3, k = 1
输出:"123"
 

提示:

1 <= n <= 9
1 <= k <= n!

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>

char * getPermutation(int n, int k)
{
	int *nums = (int *)malloc(n * sizeof(int));
	bool *flags = (bool *)malloc(n * sizeof(bool));
	char *out = (char *)malloc((n + 1) * sizeof(char));
	int i, j, len = 0;

	memset(flags, false, n * sizeof(bool));

	nums[0] = 1;
	for (i = 1; i < n; i++) {
		nums[i] = nums[i-1] * (i + 1);
	}

	assert(k <= nums[n-1]);

	//search
	i = n - 2;
	while ((i >= 0) && (k > 0)) {
		int m = k / nums[i];
		k = k % nums[i];
		int a = m + ((k > 0) ? 1 : 0);

		int count = 0;
		for (j = 0; j < n; j++) {
			if (!flags[j]) {
				count++;
			}
			if (count >= a) {
				break;
			}
		}
		flags[j] = true;
		out[len++] = j + 1 + '0';
		i--;
	}

	for (i = n-1; i >= 0; i--) {
		if (!flags[i]) {
			out[len++] = i + 1 + '0';
		}
	}

	free(flags);
	free(nums);
	out[len] = '\0';
	return out;
}

int main(int argc, char *argv[])
{
	if (argc != 3) {
		printf("please input permutation n and k!\n");
		return 0;
	}

	int n = atoi(argv[1]);
	int k = atoi(argv[2]);

	char *ret = getPermutation(n, k);

	printf("permutation n/k: %s\n", ret);
	free(ret);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这道题目可以用递归实现。首先,我们可以使用一个数组来保存每个盲盒排除的两种款式,比如说excludes[i][0]和excludes[i][1]分别表示第i个盲盒排除的两种款式。然后我们可以定义一个函数来计算所有合规的排列数: ```c++ int count_valid_permutations(int cur_box, int toys[], bool used[]) { if (cur_box == 6) { // 所有盲盒都已经选完了,检查是否合法 bool valid = true; for (int i = 0; i < 6; i++) { if (used[i] && (toys[i] == excludes[i][0] || toys[i] == excludes[i][1])) { valid = false; break; } } return valid ? 1 : 0; } // 枚举当前盲盒中可能的玩具种类 int cnt = 0; for (int i = 0; i < 6; i++) { if (!used[i]) { used[i] = true; toys[cur_box] = i; cnt += count_valid_permutations(cur_box + 1, toys, used); used[i] = false; } } return cnt; } ``` 这个函数的参数cur_box表示当前选到的盲盒编号,toys数组用于保存当前已经选了哪些玩具,used数组表示每个玩具是否已经被选过。在函数中,我们先判断是否已经选完了所有盲盒,如果是的话就检查当前的排列是否合法,如果合法就返回1,否则返回0。如果还没有选完所有盲盒,就枚举当前盲盒中可能的玩具种类,递归调用函数计算后面盲盒的排列数,并将结果累加起来。 最后,我们可以在main函数中调用这个函数来计算所有合规的排列数,并输出可能的排列序列: ```c++ int toys[6]; bool used[6] = {false}; int cnt = count_valid_permutations(0, toys, used); cout << "total valid permutations: " << cnt << endl; ``` 完整代码如下:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值