LeetCode题解-全排列的第k个数字(全排列变体)

题目

/**
 * LeetCode60 n个数的排列组合找出第k个排列
 * 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):
 "123"
 "132"
 "213"
 "231"
 "312"
 "321"

 Given n and k, return the k th permutation sequence.
 Note: Given n will be between 1 and 9 inclusive.

 时间限制:1秒
 */

分析

  1. 乍看是1~N这N个数字的全排列
  2. 变化是,每排好一个就计数,计数到k就输出当前排好的这个数
  3. 注意,如何控制数字按从小到大出现?在算法思维(递归)训练:输出字符串字符的全排列中无需考虑顺序,而且经过实验输出的数字并非完全按从小到大排列。所以需要微调swap函数

代码

public class PermutationSequence {

  int count;
  String result;

  public String getPermutation(int n, int k) {
    char[] arr = new char[n];
    for (int i = 0; i < n; i++)
      arr[i] = (char) ('1' + i);
    permutation(arr, 0, k);
    return result;
  }

  private void permutation(char[] arr, int index, int cc) {
    //至于什么时候输出,要考虑清楚
    //考虑:只有所有位置上的字符都确认即index到达末尾,才算是排好一种情况
    if (index == arr.length) {
      count++;
      // System.out.println(String.valueOf(arr));
      if (count == cc)
        result = String.valueOf(arr);
    }
    //现在index之前的字符都已就位,把之后的每个字符都交换到index这个位置
    for (int k = index; k < arr.length; k++) {
      //尝试交换
      swap1(arr, index, k);
      //交换之后index这个位置就定好了,接下来的事就是递归去解决index+1位置开始的全排列就好了
      permutation(arr, index + 1, cc);
      // 前面我们尝试交换,把全排列求出来了,交换时只尝试了一个字符,因此for循环继续之前要换回来,继续尝试交换下一个字符
      swap2(arr, index, k);
    }
  }

  private void swap1(char[] arr, int index, int k) {
    char tmp = arr[k];
    //用插入法不改变后续元素的大小顺序
    for (int i = k; i > index; i--) {
      arr[i] = arr[i - 1];
    }
    // arr[k] = arr[index];
    arr[index] = tmp;
  }

  private void swap2(char[] arr, int index, int k) {
    char tmp = arr[index];
    //用插入法不改变后续元素的大小顺序
    for (int i = index; i < k; i++) {
      arr[i] = arr[i + 1];
    }
    arr[k] = tmp;
  }

  public static void main(String[] args) {
    Instant now = Instant.now();
    //考虑极限情况消耗的时间:约19毫秒
    System.out.println(new PermutationSequence().getPermutation(9,362880));
    //结果应该是987654321,362880=9!
    System.out.println("毫秒:"+(Instant.now().toEpochMilli()-now.toEpochMilli()));
  }
}

你可能感兴趣的:(++递归与动态规划)