有1,2,3,...,n,n<=9,这n个数全排列,从小到大排好,计算第k个数是什么

从高位到低位依次选择

int findKthNumber(int n,long k){
	if(n<1||n>9||k<1) return -1;
	if(n==1){
		if(k==1){
			cout<<"1"<<endl;
			return 0;
		}else{
			return -1;
		}
	}
	long *counts = new long[n];
	bool *select = new bool[n];
	memset(select,0,n*sizeof(bool));

	counts[0] = 1;
	for(int i=1;i<n;++i){
		counts[i]=counts[i-1]*(i+1);//每个阶乘的个数
	}
	if(k>counts[n-1]){//超出最大范围
		delete[] counts;
		delete[] select;
		return -1;
	}
	long cur = 0;
	int notSelectCount = 0;
	int j=0;
	for(int i=0;i<n-1;i++){//依次从高位开始输出
		cur = (k-1)/counts[n-2-i];
		notSelectCount = 0;
		for(j =0;j<n;j++){
			if(!select[j]){//数字在前面没有输出
				++notSelectCount;
				if(notSelectCount==cur+1){
					break;
				}
			}
		}
		select[j] = true;
		cout<<j+1;
		k -= cur*counts[n-2-i];
	}

	for(j=0;j<n;j++){//最后一个数字
		if(!select[j]){
			cout<<j+1<<endl;
			break;
		}
	}

	delete[] counts;
	counts = NULL;
	delete[] select;
	select = NULL;
	return 0;
}


对于一个整数n(1≤n≤5),要输出n个数的有重复全排列,可以使用递归的方法来实现。 首先,我们定义一个函数permutation,该函数有三个参数:input_list为输入的数字列表,used为记录数字是否已被使用的列表,result为当前已生成的排列结果。函数的作用是生成n个数的有重复全排列。 在函数内部,首先判断是否已经生成了n个数排列。如果已经生成了,则将排列结果添加到最终结果列表,然后返回。 如果还没有生成n个数排列,则遍历输入的数字列表。对于每一个数字,判断该数字是否已被使用。如果已被使用,则跳过该数字,继续遍历下一个数字。如果该数字还没有被使用,则将该数字添加到排列结果,将该数字标记为已使用,然后递归调用permutation函数,继续生成下一个数字的排列。递归调用结束后,需要将排列结果和使用标记恢复到之前的状态,以便进行下一次循环。 最后,定义一个最终结果列表,将函数permutation的结果添加到其,然后输出最终结果。 以下是示例代码: def permutation(input_list, used, result): if len(result) == len(input_list): results.append(result[:]) return for i in range(len(input_list)): if used[i]: continue result.append(input_list[i]) used[i] = True permutation(input_list, used, result) result.pop() used[i] = False n = int(input("请输入一个整数n:")) input_list = [i for i in range(1, n+1)] used = [False] * n results = [] permutation(input_list, used, []) print("输出结果:") for result in results: print(result) 运行示例代码,当输入n为3时,输出结果如下: 输出结果: [1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 1, 2] [3, 2, 1] 这些就是3个数的有重复全排列的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值