zoukankan      html  css  js  c++  java
  • LeetCode: Permutation Sequence 解题报告

    Permutation Sequence

        https://oj.leetcode.com/problems/permutation-sequence/

    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 (ie, for n = 3):

    1. "123"
    2. "132"
    3. "213"
    4. "231"
    5. "312"
    6. "321"

    Given n and k, return the kth permutation sequence.

    Note: Given n will be between 1 and 9 inclusive.

    解答:

    1. 以某一数字开头的排列有(n-1)! 个。
    例如: 123, 132, 以1开头的是 2!个
    2. 所以第一位数字就可以用 (k-1) / (n-1)!  来确定 .这里K-1的原因是,序列号我们应从0开始计算,否则在边界时无法计算。
    3. 第二位数字。假设前面取余后为m,则第二位数字是 第 m/(n-2)! 个未使用的数字。
    4. 不断重复2,3,取余并且对(n-k)!进行除法,直至计算完毕

    以下为主页君的代码,敬请指正:

    解法1:

    采用比较复杂的boolean来计算数字的索引(我们需要用一个boolean的数组来记录未使用的数字):

     1 package Algorithms.permutation;
     2 
     3 /*
     4  The set [1,2,3,…,n] contains a total of n! unique permutations.
     5 
     6 By listing and labeling all of the permutations in order,
     7 We get the following sequence (ie, for n = 3):
     8 
     9     "123"
    10     "132"
    11     "213"
    12     "231"
    13     "312"
    14     "321"
    15 
    16 Given n and k, return the kth permutation sequence.
    17 
    18 Note: Given n will be between 1 and 9 inclusive.
    19  * */
    20 public class PermutationSequence {
    21     public static String getPermutation(int n, int k) {
    22         if (n == 0) {
    23             return "";
    24         }
    25         
    26         // 先计算出(n)!
    27         int num = 1;
    28         for (int i = 1; i <= n; i++) {
    29             num *= i;
    30         }
    31         
    32         boolean[] use = new boolean[n];
    33         for (int i = 0; i < n; i++) {
    34             use[i] = false;
    35         }
    36         
    37         // 因为index是从0开始计算 
    38         k--;
    39         StringBuilder sb = new StringBuilder();
    40         for (int i = 0; i < n; i++) {
    41             // 计算完第一个数字前,num要除以(n)
    42             num = num / (n - i);
    43             
    44             int index = k / num;
    45             k = k % num;
    46             
    47             for (int j = 0; j < n; j++) {                
    48                 if (!use[j]) {
    49                     if (index == 0) {
    50                         // 记录下本次的结果.
    51                         sb.append((j + 1) + "");
    52                         use[j] = true;
    53                         break;
    54                     }
    55                     
    56                     // 遇到未使用过的数字,记录index
    57                     index--;
    58                 }
    59             }
    60         }
    61         
    62         return sb.toString();
    63     }
    64 
    65     public static void main(String[] args) {
    66         System.out.println(getPermutation(3, 5));
    67     }
    68 
    69 }
    View Code

    解法2:

    优化后,使用链表来记录未使用的数字,每用掉一个,将它从链表中移除即可。

     1 public String getPermutation1(int n, int k) {
     2         // 1:17 -> 1:43
     3         LinkedList<Character> digits = new LinkedList<Character>();
     4         
     5         // bug 2: should only add n elements.
     6         for (char i = '1'; i <= '0' + n; i++) {
     7             digits.add(i);
     8         }
     9         
    10         k = k - 1;
    11         StringBuilder sb = new StringBuilder();
    12         
    13         int sum = 1;
    14         // n!
    15         for (int i = 1; i <= n; i++) {
    16             sum *= i;
    17         }
    18         
    19         int cur = n;
    20         while (!digits.isEmpty()) {
    21             sum /= cur;
    22             cur--;
    23             
    24             int digitIndex = k / sum;
    25             k = k % sum;
    26             //Line 25: error: cannot find symbol: method digits(int)
    27             sb.append(digits.get(digitIndex));
    28             // remove the used digit.
    29             digits.remove(digitIndex);
    30         }
    31         
    32         return sb.toString();
    33     }
    View Code

    解法3:

    在2解基础进一步优化,使用for 循环替代while 循环,更简洁:

     1 public String getPermutation(int n, int k) {
     2         // 1:17 -> 1:43
     3         LinkedList<Character> digits = new LinkedList<Character>();
     4         
     5         // bug 2: should only add n elements.
     6         for (char i = '1'; i <= '0' + n; i++) {
     7             digits.add(i);
     8         }
     9         
    10         // The index start from 0;
    11         k--;
    12         StringBuilder sb = new StringBuilder();
    13         
    14         int sum = 1;
    15         // n!
    16         for (int i = 1; i <= n; i++) {
    17             sum *= i;
    18         }
    19         
    20         for (int i = n; i >= 1; i--) {
    21             sum /= i;
    22             int digitIndex = k / sum;
    23             k = k % sum;
    24             
    25             //Line 25: error: cannot find symbol: method digits(int)
    26             sb.append(digits.get(digitIndex));
    27             
    28             // remove the used digit.
    29             digits.remove(digitIndex);
    30         }
    31         
    32         return sb.toString();
    33     }
    View Code

    GitHub代码链接

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4224575.html
Copyright © 2011-2022 走看看