算法:回溯七 Permutation Sequence数组全排列定位

题目

地址:https://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 for n = 3:

“123”
“132”
“213”
“231”
“312”
“321”

Given n and k, return the kth permutation sequence.

Note:

  • Given n will be between 1 and 9 inclusive.
  • Given k will be between 1 and n! inclusive.
    Example 1:
Input: n = 3, k = 3
Output: "213"

Example 2:

Input: n = 4, k = 9
Output: "2314"

回溯DFS实现

思路:
获取少一位的全排列,取商为相应的位置,把值取出来添加到结果StringBuilder对象。剩下余数继续上面的逻辑即可。

package backtracking;

import java.util.ArrayList;
import java.util.List;

// https://leetcode.com/problems/permutation-sequence/
public class PermutationSequence {

  public static void main(String[] args) {
    PermutationSequence obj = new PermutationSequence();
    String result = obj.getPermutation(4, 9);
    System.out.println("result > " + result);
  }

  public String getPermutation(int n, int k) {
    // factorial
    int[] factorial = new int[n + 1];
    factorial[0] = 1;
    int sum = 1;

    // create an array of factorial lookup
    for (int i = 1; i <= n; i++) {
      sum *= i;
      // factorial[] = {1, 1, 2, 6, 24, ..., n!}
      factorial[i] = sum;
    }

    // create a list of numbers to get indices
    List<Integer> items = new ArrayList<Integer>();
    for (int i = 1; i <= n; i++) {
      // numbers = {1, 2, 3, 4}
      items.add(i);
    }

    // i from 0, so k - 1
    k--;

    StringBuilder sb = new StringBuilder();
    // calculate
    for (int i = 1; i <= n; i++) {
      int index = k / factorial[n - i];
      int item = items.get(index);
      sb.append(String.valueOf(item));
      items.remove(index);
      k -= index * factorial[n - i];
    }

    return sb.toString();
  }
}

英文详细分解

如果上面的代码看不明白,下面详细分解。

“Explain-like-I’m-five” Java Solution in O(n)

I’m sure somewhere can be simplified so it’d be nice if anyone can let me know. The pattern was that:

say n = 4, you have {1, 2, 3, 4}

If you were to list out all the permutations you have

1 + (permutations of 2, 3, 4)

2 + (permutations of 1, 3, 4)

3 + (permutations of 1, 2, 4)

4 + (permutations of 1, 2, 3)

We know how to calculate the number of permutations of n numbers… n! So each of those with permutations of 3 numbers means there are 6 possible permutations. Meaning there would be a total of 24 permutations in this particular one. So if you were to look for the (k = 14) 14th permutation, it would be in the

3 + (permutations of 1, 2, 4) subset.

To programmatically get that, you take k = 13 (subtract 1 because of things always starting at 0) and divide that by the 6 we got from the factorial, which would give you the index of the number you want. In the array {1, 2, 3, 4}, k/(n-1)! = 13/(4-1)! = 13/3! = 13/6 = 2. The array {1, 2, 3, 4} has a value of 3 at index 2. So the first number is a 3.

Then the problem repeats with less numbers.

The permutations of {1, 2, 4} would be:

1 + (permutations of 2, 4)

2 + (permutations of 1, 4)

4 + (permutations of 1, 2)

But our k is no longer the 14th, because in the previous step, we’ve already eliminated the 12. 4-number permutations starting with 1 and 2. So you subtract 12 from k… which gives you 1. Programmatically that would be…

k = k - (index from previous) * (n-1)! = k - 2*(n-1)! = 13 - 2*(3)! = 1

In this second step, permutations of 2 numbers has only 2 possibilities, meaning each of the three permutations listed above a has two possibilities, giving a total of 6. We’re looking for the first one, so that would be in the 1 + (permutations of 2, 4) subset.

Meaning: index to get number from is k / (n - 2)! = 1 / (4-2)! = 1 / 2! = 0… from {1, 2, 4}, index 0 is 1

so the numbers we have so far is 3, 1… and then repeating without explanations.

{2, 4}

k = k - (index from pervious) * (n-2)! = k - 0 * (n - 2)! = 1 - 0 = 1;

third number’s index = k / (n - 3)! = 1 / (4-3)! = 1/ 1! = 1… from {2, 4}, index 1 has 4

Third number is 4

{2}

k = k - (index from pervious) * (n - 3)! = k - 1 * (4 - 3)! = 1 - 1 = 0;

third number’s index = k / (n - 4)! = 0 / (4-4)! = 0/ 1 = 0… from {2}, index 0 has 2

Fourth number is 2

Giving us 3142. If you manually list out the permutations using DFS method, it would be 3142. Done! It really was all about pattern finding.

代码下载

https://github.com/zgpeace/awesome-java-leetcode/blob/master/code/LeetCode/src/backtracking/PermutationSequence.java

参考

https://leetcode.com/problems/permutation-sequence/discuss/22507/%22Explain-like-I’m-five%22-Java-Solution-in-O(n)

发布了127 篇原创文章 · 获赞 12 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zgpeace/article/details/103825391
今日推荐