/*
给定参数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,退出条件是什么