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

你可能感兴趣的:(LeetCode)