一、题目
1、审题
2、分析
给两个数字 n 与 k,返回 1-n 所有数字组成的从小到大的全排序的第 k 个数。
二、解答
1、思路:
方法一、采用字典序列,返回全部序列后,输出第 k 个。(时间超出,但代码可行)
public String getPermutation(int n, int k) { Integer num = 0; int i = 1; while(i <= n) num = num*10 + i++; List<String> result = new ArrayList<>(); result.add(num.toString()); helper(result, new StringBuffer().append(num), n-1, n); for(String s: result) System.out.println(s); System.out.println(); return result.get(k-1).toString(); } private void helper(List<String> result, StringBuffer sb, int index, int len) { if(index < 0) return; // 1、查找比 index 大的最小的数的 index int tmpIndex = -1; for(int i = len - 1; i > index; i--) { if(sb.charAt(i) > sb.charAt(index)) { tmpIndex = i; break; } } if(tmpIndex != -1) { // 交换字符 char c = sb.charAt(tmpIndex); sb.setCharAt(tmpIndex, sb.charAt(index)); sb.setCharAt(index, c); // 2、 翻转 index 后面部分 String s = sb.substring(index+1); StringBuffer tmpBuffer = new StringBuffer(s).reverse(); // add sb.delete(index+1, len) .append(tmpBuffer.toString()); result.add(sb.toString()); helper(result, sb, len-2, len); } else { helper(result, sb, index - 1, len); } }
方法二、采用数学的思维方法:
以 n = 4, k = 9 为例:
①、总共有 n! = 4!=4 X 3! = 24种排序。可以分为:
1 和 {2, 3, 4}
2 和 {1, 3, 4}
3 和 {1, 2, 4}
4 和 {1,2,3}
的排序。
② 对于数组 nums = {1, 2, 3, 4},要确定第一个数字的下标,则
K = 8 ;(由于排序的集合开始的下标是0,所以 K = 9 -1 = 8;)
index = K/ (n-1)! = 8 / (4-1)! = 8/6 = 1; 即确定第一个数字: nums[1] = 2
③、由 ① 知,确定了第一个数字 2,即排除了数字 1 开始的所有排序,则剩下的待确定的 K 为:
K = K - index * (n - 1)! = 8 - 1*(4-1)! = 8 - 6 = 2
于是: index = K /( n - 2)! = 2 / 2! = 1 ,
则,对于数组 nums = {1, 3, 4} ,确定了数字 nums[1] = 3;
④ 同理:
K = K - index*(n-2)! = 2 - 1*(4-2)! = 0;
index = K/(n-3)! = 0 / (n - 3)! = 1 / 1 = 0;
则对于数组 nums = {1, 4}, 确定了数字 nums[0] = 1;
⑤
K = K - Index * (n - 3)! = 0 - 0 * 1 = 0
Index = 0 /(n-4)! = 0
则对于数组 nums = {4},确定了数字 nums[0] = 4
综上,对于 n = 4, k = 9 的排序为: 2314.
class Solution { public String getPermutation(int n, int k) { List<Integer> numbers = new LinkedList<Integer>(); int[] factorial = new int[n+1]; StringBuilder sb = new StringBuilder(); // factorial[] = {1, 1, 2, 6, ... , n!} int sum = 1; factorial[0] = 1; for(int i = 1; i <= n; i++) { sum *= i; factorial[i] = sum; } // list = {1, 2, 3, 4} , get indices for (int i = 1; i <= n; i++) { numbers.add(i); } k--; for(int i = 1; i <= n; i++) { int index = k / factorial[n-i]; sb.append(numbers.remove(index)); k -= index*factorial[n-i]; } return String.valueOf(sb); } }