题目80:第k个排列

/*
给定参数n,从1到n会有n个整数:1,2,3,…,n,
这n个数字共有n!种排列.
按大小顺序升序列出所有排列的情况,并一一标记,
当n=3时,所有排列如下:
“123” “132” “213” “231” “312” “321”
给定n和k,返回第k个排列.

  输入描述:
    输入两行,第一行为n,第二行为k,
    给定n的范围是[1,9],给定k的范围是[1,n!]。
  输出描述:
    输出排在第k位置的数字。

  实例1:
    输入:
      3
      3
    输出:
      213
    说明
      3的排列有123,132,213...,那么第三位置就是213

  实例2:
    输入
      2
      2
    输出:
      21
    说明
      2的排列有12,21,那么第二位置的为21

*/

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<vector>
#include<stdio.h>
#include<string>
#include <algorithm>
//********1)printf调试的方法也是听有用的,比调试快速一些。**********
//********2)用class类的方式写比C方式写在函数调用时参数少一些,更简洁。**********
using namespace std;
void backtracking(vector<int>&arr ,vector<int>&one_res, vector<vector<int>>& result, vector<bool>&used)
{	
	if (one_res.size()==used.size() ) //一个数据完成后的元素数量和used相同
	{
		result.push_back(one_res);
		return;
	}
	
	for (int i = 0; i < arr.size(); i++)//这里的i开始取值很关键,因为是2,1和1,2是不同的,每次要从0开始、
	{
		if (used[i] == true) {
			continue;
		}
		used[i] = true;//不标记的话one_res数组会多次添加重复的数据
		one_res.push_back(arr[i]);
		backtracking(arr, one_res, result,used);//不用传元素的下标,因为排列是有顺序的(都要从头开始),不用特别记录下次递归的位置。
		one_res.pop_back();//每次函数回退,都删一个
		used[i] = false;
	}

}
int main()
{
	int num, k = 0;
	vector<int>arr;
	vector<int>one_res;
	vector<vector<int>>result;

	cin >> num;//指定0~num个数

	for (int i = 1; i <= num; i++)
	{
		arr.push_back(i);
		
	}
	
	vector<bool> used(arr.size(), false);//vector的初始化第一个是初始的个数,第二个是值初始
	//判断递归退出的重要条件就是这个数据比如(1,3,2)都放完了吗?used数组也是退出条件
	cin >> k;
	backtracking(arr, one_res, result, used);//
	//参数传的多可以用classC++方式定义类去写,以后就这么做。当然出重也可以以C的方式写。就是参数多一些
	//sort(result.begin(), result.end());//递归形成的元素顺序是从小到大排好的(初始数组是递增序列)
	for (int j = 0; j < result[k-1].size(); j++)
	{	
		cout << result[k-1][j] ;
	}
	//cout << *(result[k-1].begin())<< endl;//错误的输出方式,只是输出了一个元素
	return 0;
}

做题之前也要画出来 过一遍 到底循环传0还是startindex,退出条件是什么

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值