• 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代码链接

  • 相关阅读:
    day10函数嵌套
    day 9
    day 8函数
    day7预习
    合唱队形(解题思维的锻炼)
    Cow Exhibition (背包中的负数问题)
    Investment(完全背包)
    Cash Machine(多重背包二进制转换)
    Milking Time(DP)
    Brackets Sequence(升级版)
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4224575.html
Copyright © 2020-2023  润新知