美文网首页
0060. 第 k 个排列

0060. 第 k 个排列

作者: 蓝笔头 | 来源:发表于2021-08-25 08:11 被阅读0次

题目地址

https://leetcode-cn.com/problems/permutation-sequence/

题目描述

给出集合 [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"

题解

回溯算法

class Solution {
    private int targetK = 0;
    private String target = "";

    public String getPermutation(int n, int k) {
        targetK = k;
        boolean[] used = new boolean[n + 1];
        dfs(n, used, "");
        return target;
    }

    public void dfs(int n, boolean[] used, String permutation) {
        if (permutation.length() == n) {
            targetK--;
            if (targetK == 0) {
                target = permutation;
            }
            return;
        }
        for (int i = 1; i <= n; ++ i) {
            // 过滤已选择的
            if (used[i]) continue;

            // 做选择
            used[i] = true;
            
            dfs(n, used, permutation + i);
            
            // 撤销选择
            used[i] = false;
        }
    }
}

数学计算

对于 n 位数的排列,第一位数固定的情况下,后面的看成是 n-1 位数的排列。
因此以 1, 2, 3, ..., n 中一个数开头的排列有 (n-1)! 个。

  • (1)假设 range = (n-1)!,那么有:
    • 1 开头的排列占据 0 ~ range-1
    • 2 开头的排列占据 range ~ (2*range)-1
    • 3 开头的排列占据 2*range ~ (3*range)-1
    • ...
    • n 开头的排列占据 (n-1)*range ~ (n*range)-1
  • (2)因为数组下标从 0 开始,所以用 index = k / range 就可以选出第一位的数字是什么。
  • (3)k -= (index * range),从第(1)步开始轮询即可。
  • 使用 String 拼接字符串
class Solution {
    public String getPermutation(int n, int k) {
        int[] nums = new int[n];
        for (int i = 0; i < n; ++ i) {
            nums[i] = i + 1;
        }

        return getPermutation(nums, k);
    }

    public String getPermutation(int[] nums, int k) {
        String permutation = "";

        int n = nums.length;
        for (int i = 0; i < n; ++ i) {
            int range = factorial(n - i - 1);
            int index = getIndex(k, range);
            
            permutation += nums[index];

            k -= (index * range);
            nums[index] = Integer.MAX_VALUE;
            Arrays.sort(nums);
        }

        return permutation;
    }

    public int getIndex(int k, int range) {
        int index = k / range;
        if (k % range == 0) {
            index = index - 1;
        }
        return index;
    }

    public int factorial(int n) {
        int result = 1;
        for (int i = 2; i <= n; ++ i) {
            result *= i;
        }
        return result;
    }
}
  • 使用 StringBuilder 拼接字符串
class Solution {
    public String getPermutation(int n, int k) {
        int[] nums = new int[n];
        for (int i = 0; i < n; ++ i) {
            nums[i] = i + 1;
        }

        return getPermutation(nums, k);
    }

    public String getPermutation(int[] nums, int k) {
        StringBuilder permutation = new StringBuilder(); // 变更

        int n = nums.length;
        for (int i = 0; i < n; ++ i) {
            int range = factorial(n - i - 1);
            int index = getIndex(k, range);
            
            permutation.append(nums[index]); // 变更

            k -= (index * range);
            nums[index] = Integer.MAX_VALUE;
            Arrays.sort(nums);
        }

        return permutation.toString(); // 变更
    }

    public int getIndex(int k, int range) {
        int index = k / range;
        if (k % range == 0) {
            index = index - 1;
        }
        return index;
    }

    public int factorial(int n) {
        int result = 1;
        for (int i = 2; i <= n; ++ i) {
            result *= i;
        }
        return result;
    }
}

相关文章

  • 0060. 第 k 个排列

    题目地址 https://leetcode-cn.com/problems/permutation-sequenc...

  • 第k个排列

    https://leetcode-cn.com/explore/interview/card/bytedance/...

  • 输出数组的全排列

    思想: n 个元素数组全排列 = 第 1 个前缀 + 后 n - 1 个元素全排列 输出第 k 个元素之后的全排列...

  • 子集、全排列、第k个排列

    子集输出 全排列输出 存在重复数字的全排列 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。 按大...

  • 排列类算法问题大总结

    全排列 带重复元素的排列 下一个排列 上一个排列 第 k 个排列 排列序号 排列序号II 全排列 给定一个数字列表...

  • LeetCode:第k个排列

    第k个排列 题目叙述: 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。按大小顺序列出所有排列情况...

  • 60.第k个排列

  • 60. 第k个排列

    题目描述 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。按大小顺序列出所有排列情况,并一一标记,...

  • 011-第K个排列

    描述 一个序列[1, 2, 3, 4, ..., n]一共有n!个排列,写一个算法计算第k个排列; 分析 直观的方...

  • 60. 第k个排列

    给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。 按大小顺序列出所有排列情况,并一一标记,当 n ...

网友评论

      本文标题:0060. 第 k 个排列

      本文链接:https://www.haomeiwen.com/subject/zcwkiltx.html