排列序列

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

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。

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

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

最容易的当然还是暴力递归,直到找到目标序列结束。但是没有用到题目给定的规律。
所以要找规律。这道题如果直接去想规律的话。不太好想。可以先换一种角度。假设现在已经给定了排列和n。求k值。
比如:给定 “213” 和 3。那么如何求k呢?
k = 1 * (n - 1)! + 0 * (n - 2)! + 0 * (n - 3)! + 1
关于这个式子的解释:对第一个数2来说,比2小的数有1,那么以1为第一个数共有 (n - 1)!个。同理,对于第二个数1来说,目前尚未用到的且比它小的数有0个。所以是 0 * …。直到最后把213之前的序列数量都算出来求和,最后 + 1。即为k的值。
回到本题,现在给定k值和n,求序列。也就是上述过程的逆过程。只需不断的求商求余就能确定序列每一个位置的值。

class Solution {
    public String getPermutation(int n, int k) {
        // 下标0表示数字1是否被用过
        boolean[] isUse = new boolean[n];
        StringBuilder sb = new StringBuilder();
        int[] factorial = new int[n];
        factorial[0] = 1;
        for (int i = 1; i < n; ++i) {
            factorial[i] = factorial[i - 1] * i;
        }

        --k;
        for (int i = n - 1; i > -1; --i) {
            int a = k / factorial[i] + 1;
            int tag = 0;
            for (int j = 0; j < n; ++j) {
                tag = isUse[j] ? tag : tag + 1;
                if (tag == a) {
                    sb.append(j + 1);
                    isUse[j] = true;
                    break;
                }
            }

            k %= factorial[i];
        }

        return sb.toString();
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值