leetcode习题集——60. 第k个排列

版权声明:转载请注明出处,请勿商用谢谢! https://blog.csdn.net/qq_34064803/article/details/89706618

题目

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当n = 3 时, 所有排列如下:
"123" "132" "213" "231" "312" "321"
给定 n 和 k,返回第 k 个排列。

说明:

给定 n 的范围是 [1, 9]
给定 k 的范围是[1, n!]

示例 1:
输入: n = 3, k = 3
输出: “213”

示例 2:
输入: n = 4, k = 9
输出: “2314”

算法1

public class P60_PermutationSequence {
    public String getPermutation(int n, int k) {
        int[] nums = new int[n];
        for(int i = 0;i<n;i++){
            nums[i] = i+1;
        }
        for(int i=1;i<k;i++){
            nextPermutation(nums);
        }
        StringBuilder s = new StringBuilder();
        for(int i = 0;i<n;i++){
            s.append(nums[i]);
        }
        return s.toString();
    }
    private void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        while (i >= 0 && nums[i + 1] <= nums[i]) {
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1);
    }

    private void reverse(int[] nums, int start) {
        int i = start, j = nums.length - 1;
        while (i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

思路:
参考leetcode习题集——31. 下一个排列

  • 从第一个排列按顺序求到第k个排列

算法2

public class P60_PermutationSequence2 {
    public String getPermutation(int n, int k) {
        char[] arr = new char[n];
        //第1个排列
        for (int i = 1; i <= n; i++) {
            arr[i - 1] = (char) (i + '0');
        }

        int cur = 0;
        int remain = k - 1;
        while (remain > 0) {
            int step = getFactorial(n - cur - 1);
            int loop = remain / step;

            for (int i = 1; i <= loop; i++) {
                char tmp = arr[cur];
                arr[cur] = arr[cur + i];
                arr[cur + i] = tmp;
            }

            remain = remain % step;
            cur++;
        }

        return new String(arr);
    }
    private int getFactorial(int n) {
        int ret = 1;
        for (int i = 2; i <= n; i++) {
            ret *= i;
        }
        return ret;
    }
}

思路:
在这里插入图片描述

  1. 从左开始遍历,当前遍历的下标为cur,当前剩余排列数remain=k-1
  2. cur开始的n-cur-1会产生(n-cur-1)!个排列,取名为step
  3. loopremainstep的商,代表消耗的顺序排列次数
    在这里插入图片描述
  • loop 为1,即下(n-cur-1)!个排列即为交换后的结果
    在这里插入图片描述
  • loop 为1,即下(n-cur-1)!个排列即为交换后的结果,后续的依此类推
  1. 重复以上过程直到remain0

猜你喜欢

转载自blog.csdn.net/qq_34064803/article/details/89706618