LeetCode/solutions/60. Permutation Sequence.md
2019-02-02 21:12:43 +08:00

69 lines
2.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [60. Permutation Sequence](https://leetcode.com/problems/permutation-sequence/)
# 思路
给定整数n返回数组[1,2,...,n]的第k个permutation。
## 思路一
STL中有函数next_permutation可以返回一个数组的下一个permutation所以最简单的思路就是执行这个函数k-1次即可得到第k个permutation。
next_permutation的时间复杂度是O(n), 所以总的复杂度就是O(kn), 空间复杂度O(1)
## 思路二
让我们仔细看看n=3的例子
```
1. "123"
2. "132"
3. "213"
4. "231"
5. "312"
6. "321"
```
可以看到第一个元素分别为1、1、2、2、3、3所以我们可以根据k的值直接得到结果的第一个元素例如若k=3那么结果第一元素就是2。
一般化一点所有排列中第一个元素为1~n每个都出现了(n-1)!次可根据k直接得到结果的第一个元素值可以根据同样的思路得到第2、3...直至整个结果。
时间复杂度O(n^2), 空间复杂度O(n), 因为k可以比n大很多所以比思路一快很多。
# C++
## 思路一
``` C++
class Solution {
public:
string getPermutation(int n, int k) {
string res = "";
for(int i = 0; i < n; i++) res += (i + '1');
while(--k){
next_permutation(res.begin(), res.end());
}
return res;
}
};
```
## 思路二
``` C++
class Solution {
private:
char get_k_th_not_0(vector<int> &nums, int k){ // 获得第k个还没用过的数字对应的字符
k += 1; // 传进来的k是从0开始的
int i = -1;
while(k--){
i++;
while(i < nums.size() && nums[i] == 0) i++;
}
nums[i] = 0; // 数字i(对应字符i+"1")已经用过了更新nums
return i + '1';
}
public:
string getPermutation(int n, int k) {
string res = "";
vector<int>nums(n, 1); // 若nums[i]=1说明数字i(对应字符i+"1")还没用过
int product = 1;
k -= 1; // 从0开始
for(int i = 1; i <= n; i++) product *= i; // product = n!
for(int i = n; i >= 1; i--){
product /= i; // 此时k代表每个第一个元素出现的次数
int tmp = k / product;
k %= product; // 更新k
res += get_k_th_not_0(nums, tmp);
}
return res;
}
};
```