leetcode 60. 排列序列
给出集合 [1,2,3,...,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
示例 1:
输入:n = 3, k = 3
输出:"213"
示例 2:
输入:n = 4, k = 9
输出:"2314"
示例 3:
输入:n = 3, k = 1
输出:"123"
提示:
1 <= n <= 9
1 <= k <= n!
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
大多数的解法是回溯,从小到大统计每个数字。
其实排序之后是有规律的,可以不用回溯,直接归纳每个数字出现的位置,直接拼接字符串。
public String getPermutation(int n, int k) { // 先把集中特殊的情况直接返回 if (n == 1) { return "1"; } if (n == 2) { if (k == 1) { return "12"; } return "21"; } StringBuilder sb = new StringBuilder(n); if (k == 1) { for (int i = 0; i < n; i++) { sb.append(i + 1); } return sb.toString(); } // 开始一般的形式 int a = 1; int limit = 0; for (int i = 2; i <= n; i++) { a *= i; limit = i; if (a > k) { break; } } int[] arr = new int[n]; Arrays.fill(arr, -1); int d = 0; for (int i = n - limit; i > 0; i--) { arr[d++] = 1; } a /= limit; int p; int z = d; while (k != 0) { p = k / a; k = k % a; if (k != 0) { p++; } else { if (z + 1 < n) { arr[z + 1] = 0; } } a /= (--limit); if (z + 1 < n) { arr[z++] = p; } } int[] arr2 = new int[n]; for (int i = 0; i < n; i++) { arr2[i] = i + 1; } for (int i = 0; i < n; i++) { int index = arr[i]; if (index == 0) { for (int j = n - 1; j >= 0; j--) { if (arr2[j] != 0 && arr2[j] != -1) { sb.append(arr2[j]); } } break; } if (index == -1) { for (int j = 0; j < n; j++) { if (arr2[j] != 0 && arr2[j] != -1) { sb.append(arr2[j]); } } break; } int value = get(arr2, index, n); sb.append(value); } return sb.toString(); } /** * 获取数组中的值 * @param arr * @param index * @param n * @return */ private static int get(int[] arr, int index, int n) { int num = 1; for (int j = 0; j < n; j++) { int i = arr[j]; if (i != 0 && i != -1) { if (index == num) { arr[j] = -1; return i; } num++; } else if (i == 0) { return i; } } return -1; }
写法比较复杂,但是时间上可以100%.