Leetcode算法Java全解答--60. 第k个排列

超、凢脫俗 2022-04-05 08:58 241阅读 0赞

Leetcode算法Java全解答–60. 第k个排列

文章目录

  • Leetcode算法Java全解答—60. 第k个排列
    • 题目
    • 想法
    • 结果
    • 总结
    • 代码
      • 我的答案
      • 大佬们的答案
      • 测试用例
    • 其他

题目

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。

说明:

给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。

  1. 示例 1:
  2. 输入: n = 3, k = 3
  3. 输出: "213"
  4. 示例 2:
  5. 输入: n = 4, k = 9
  6. 输出: "2314"

想法

k要先变成k-1,因为现在用的是下标值,是以0开头的,k–;

用k对(n-1)!取商,结果为数据 余数为下一个数字

  1. 比如n=4,这样排列出来的数据就有[1234,1243,1324,1342,1423,1432,2134,
  2. 2143,2314,2341,2413,2431,3124...]
  3. 第一轮:
  4. 可以看到以1开头的有3*2*1 = 6种,同理2.3.4的都是这样
  5. 这样8/6 = 1..2(商为1,余数为2), 结果数据就是索引为12(第0个是1
  6. 然后把2从数组中移除
  7. 第二轮
  8. 这时候数据把2除外就有[134,143,314,341,413,431]
  9. 可以看到以1开头的有2*1 = 2种,同理3.4的都是这样
  10. 上一把余数是2,所以2/2 = 1..0,结果数据就是索引为13(第0个是1
  11. 第三轮
  12. 这时候数据把2除外就有[14,41]
  13. 可以看到以1开头的有1 =1种,同理4的都是这样
  14. 上一把余数是0,所以0/1 = 0..1,结果数据就是索引为01(第0个是1

结果

超过99%的测试案例

时间复杂度/空间复杂度:n/n

总结

k–那里没有想到

代码

我的答案

  1. public String getPermutation(int n, int k) {
  2. if (n <= 1) {
  3. return "" + n;
  4. }
  5. ArrayList arrayList = new ArrayList();
  6. for (int i = 1; i <= n; i++) {
  7. arrayList.add(i);
  8. }
  9. StringBuilder result = new StringBuilder();
  10. int leaf = n;
  11. k = k - 1;
  12. while (leaf > 0) {
  13. // 循环求出(n-1)阶乘
  14. int val = 1;
  15. for (int i = 1; i <= leaf - 1; i++) {
  16. val = val * i;
  17. }
  18. // 求出下标索引index
  19. int index = k / val;
  20. result.append(arrayList.get(index));
  21. arrayList.remove(index);
  22. k = k % val;
  23. leaf--;
  24. }
  25. return result.toString();
  26. }

大佬们的答案

  1. public String better(int n, int k) {
  2. List<Integer> b = new ArrayList<>();
  3. int a[] = new int[n];
  4. int j = 0;
  5. for (int i = 0; i <= n; i++) {
  6. b.add(i);
  7. }
  8. for (int i = n; i > 0; i--) {
  9. if (k == 0) {
  10. for (int g = b.size() - 1; g >= 1; g--) {
  11. a[n - i - 1 + g] = b.get(b.size() - g);
  12. }
  13. break;
  14. }
  15. j = pa(i - 1);
  16. int l = k / j + 1;
  17. if (k % j != 0) {
  18. a[n - i] = b.get(l);
  19. b.remove(l);
  20. } else {
  21. a[n - i] = b.get(l - 1);
  22. b.remove(l - 1);
  23. }
  24. k = k % j;
  25. }
  26. String s = integerFormatString(a);
  27. return s;
  28. }
  29. private int pa(int n) {
  30. int k = 1;
  31. if (n == 0) {
  32. return 1;
  33. }
  34. for (int i = 1; i <= n; i++) {
  35. k = k * i;
  36. }
  37. return k;
  38. }
  39. public static String integerFormatString(int[] a) {
  40. int len = a.length;
  41. char[] ch = new char[len];
  42. for (int i = 0; i < len; i++) {
  43. switch (a[i]) {
  44. case 0:
  45. ch[i] = '0';
  46. break;
  47. case 1:
  48. ch[i] = '1';
  49. break;
  50. case 2:
  51. ch[i] = '2';
  52. break;
  53. case 3:
  54. ch[i] = '3';
  55. break;
  56. case 4:
  57. ch[i] = '4';
  58. break;
  59. case 5:
  60. ch[i] = '5';
  61. break;
  62. case 6:
  63. ch[i] = '6';
  64. break;
  65. case 7:
  66. ch[i] = '7';
  67. break;
  68. case 8:
  69. ch[i] = '8';
  70. break;
  71. case 9:
  72. ch[i] = '9';
  73. break;
  74. default:
  75. break;
  76. }
  77. }
  78. String str = new String(ch);
  79. return str;
  80. }

测试用例

  1. @Test
  2. public void test060() {
  3. // 创建测试案例
  4. int n1 = 3;
  5. int k1 = 3;
  6. int n2 = 3;
  7. int k2 = 6;
  8. // 测试案例期望值
  9. String expResult1 = "213";
  10. String expResult2 = "321";
  11. // 执行方法
  12. Solution060 solution060 = new Solution060();
  13. String result1 = solution060.getPermutation(n1,k1);
  14. String result2 = solution060.getPermutation(n2,k2);
  15. // 判断期望值与实际值
  16. Assert.assertEquals(expResult1, result1);
  17. Assert.assertEquals(expResult2, result2);
  18. }

其他

代码托管码云地址:https://gitee.com/lizhaoandroid/LeetCodeAll.git

查看其他内容可以点击专栏或者我的博客哈:https://blog.csdn.net/cmqwan

“大佬们的答案” 标签来自leetcode,侵权请联系我进行删改

如有疑问请联系,联系方式:QQ3060507060

发表评论

表情:
评论列表 (有 0 条评论,241人围观)

还没有评论,来说两句吧...

相关阅读