题目来源:https://leetcode.com/problems/permutation-sequence/
问题描述
60. Permutation Sequence
Medium
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 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.
- Given k will be between 1 and n! inclusive.
Example 1:
Input: n = 3, k = 3
Output: "213"
Example 2:
Input: n = 4, k = 9
Output: "2314"
------------------------------------------------------------
题意
给定正整数n和k,求1~n的 k个排列。约定1<= n <= 9.
------------------------------------------------------------
思路
用一个ArrayList维护1~n的数组。循环求k(实际上是k-1,因为下标从0开始)相对于(n-1)!, (n-2)!, …, 1!的余数ans,将ArrayList中的第ans个数删除并加入到结果字符串中。
实现上有两个注意点:
1. 理论上数组可以选ArrayList也可以选LinkedList,因为算法同时涉及数组的随机索引和数组的删除操作(ArrayList随机索引O(1),删除O(n);LinkedList随机索引O(n),删除O(1)),但实测ArrayList更快。
2. 用一个数组保存(n-1)!, (n-2)!, …, 1!的结果而不是循环的时候每次计算,这样计算阶乘部分的时间复杂度可以从O(n^2)降为O(n)
------------------------------------------------------------
代码
class Solution {
public String getPermutation(int n, int k) {
int[] fac = new int[n];
fac[0] = 1;
int i = 0;
for (i=1; i<n; i++)
{
fac[i] = fac[i-1] * i;
}
int ans = 0;
k--;
List<Integer> ilist = new ArrayList<Integer>();
for (i=1; i<=n; i++)
{
ilist.add(i);
}
StringBuilder sb = new StringBuilder();
i = n - 1;
while (k > 0)
{
ans = k / fac[i];
sb.append(String.valueOf(ilist.remove(ans)));
k = k % fac[i--];
}
for (int elem: ilist)
{
sb.append(String.valueOf(elem));
}
return sb.toString();
}
}