#include <iostream>
#include <stdio.h>
#include <vector>
#include <sstream>
using namespace std;
/*
问题:
Total Accepted: 74373
Total Submissions: 272450
Difficulty: Medium
Contributors: Admin
The set [1,2,3,…,n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive.
分析:
这道题目实际之前做过。之前一道题目是给定一个排列,返回下一个序列。
现在这道题目没有给定一个排列。如果我们是以第一个排列为基准,那么
时间复杂度其实就是O(n!)。
给定一个排列,下一个排列是略微大于该排列的,比如132下一个排列是213
1】那么需要找到最高位的较大的数字替换,2】并把最高位后面的部分调整为最小的数字
设数组为A
步骤1】:寻找最高位较大的数字,从后向前,找到第一个顺序的即可,即找到A[i] > A[i+1]中的位置i来替代A[i]
步骤2】:下面需要寻找替代A[i]的数字,该数字必须是>A[i]的数字中最小的一个
需要从A[len ... 1]中从后向前寻找第一个大于A[i]的元素,记为A[j],然后swap(A[i],A[j])
步骤3】:将A[i]之后的A[i+1 ... len]元素需要变成最小的数字,此时只需要对A[i+1 ... len]逆置,因为此时的
A[i+1 ... len]已经是降序排列的,逆置后变成升序,必然是最小的
输入:
3(n) 4(k)
4 14
输出:
231
3142
关键:
1 果然超时。用另外一种方法:以{1,2,3,4}举例,共有24中排列。
其中1开头的排列6种,2排列的6种,...
因此加入给定k=14,从编程角度下标从0开始,则k-1=13,则必定在以3开头的里面,减去1,2开头排列,应该是在去除3之后的
{1,2,4}组成的排列中的第2个。 index = 13 / (4-1)! = 1,对应下标为2,剩余k = 13 - index * (4-1)! = 1,【选择了3,剩余{1,2,4}】
而{1,2,4}重复上述操作,共产生3!=6种排列,其中1开头的占有2个排列。
因此index = 1 / (4-2)! = 0,【选择了1,剩余{2,4}】
剩余k=1 - index * (4-2)! = 1,
index = k / (4-3)! = 1,【选择了4,剩余{2}】
k = 1 - index * (4-3)! = 0,
index = 0,【选择了2,剩余空{}】
最终3142
2 nums.erase(nums.begin() + index , nums.begin() + index + 1);//注意删除的时候,后面的位置取不到
*/
class Solution {
public:
//获取排列str下面一个排列
string getNext(string str)
{
if(str.empty())
{
return "";
}
int len = str.length();
bool isFind = false;
int i;
for(i = len - 2 ; i >= 0 ; i--)
{
//从后向前寻找第一个顺序的数
if(str.at(i) < str.at(i+1))
{
isFind = true;
break;
}
}
//如果没有找到,说明是逆序的,直接返回
if(!isFind)
{
return str;
}
//寻找替代A[i]的元素,从后向前找到第一次大于A[i]的元素A[j]
int j;
for(j = len - 1; j >= 0 ; j--)
{
if(str.at(j) > str.at(i))
{
break;
}
}
//交换元素A[i],A[j]
char ch = str.at(i);
str.at(i) = str.at(j);
str.at(j) = ch;
//逆置A[i+1...len-1]
reverse(str.begin() + i + 1 , str.end());
return str;
}
string getPermutation2(int n, int k) {
if(n <= 0 || k <= 0)
{
return "";
}
stringstream stream;
for(int i = 1 ; i <= n ; i++)
{
stream << i;
}
string first = stream.str();
if(k == 1)
{
return first;
}
string result;
for(int i = 2 ; i <= k ; i++)
{
result = getNext(first);
first = result;
}
return result;
}
string getPermutation(int n, int k) {
if(n <= 0 || k <= 0)
{
return "";
}
vector<int> nums;
for(int i = 1 ; i <= n ; i++)
{
nums.push_back(i);
}
k--;
vector<int> fact(n + 1 , 1);
for(int i = 1 ; i <= n; i++ )
{
fact.at(i) = i * fact.at(i-1);
}
int index;
stringstream stream;
for(int i = 1 ; i <= n ; i++)
{
index = k / fact.at(n-i);//计算下标
stream << nums.at(index);
//删除已经选中的数字
nums.erase(nums.begin() + index , nums.begin() + index + 1);//注意删除的时候,后面的位置取不到
k -= index * fact.at(n-i);
}
string result = stream.str();
return result;
}
};
void process()
{
Solution solution;
int n;
int k;
while(cin >> n >> k)
{
string result = solution.getPermutation(n , k);
cout << result << endl;
}
}
int main(int argc , char* argv[])
{
process();
getchar();
return 0;
}
leecode 解题总结:60. Permutation Sequence
最新推荐文章于 2024-07-06 07:33:24 发布