LeetCode 60. Permutation Sequence 简洁高效的解法

问题

LeetCode 400题
集合[1,2,3……,n]共包含n!不同的排列,把他们从小到大排序可以得到:

"123"
"132"
"213"
"231"
"312"
"321"

现在给定 n n n k k k,找到第 k k k个全排列。

解析

回溯是解决全排列问题的最最最通用的解法,当然,同样适用于该问题。但是用回溯解决该问题复杂度实在太高,而且这里不需要求得所有的全排列,只需要求第 k k k个全排列,所以我们可以转变一下思路。我们先看一下第 k k k个全排列有没有什么规律。
当n=3时,前两个数是1开头,中间两个数是2开头,最后面两个数是3开头。那么当 1 < = k < = 2 1<=k<=2 1<=k<=2时,第 k k k个全排列的第一位是1;依次类推得到k的取值范围和第一位对应的关系。
我们能不能按照这样的规律继续深入下去确定第二位,第三位? 答案是肯定的。假设我们确定了第一位数是1,那么第二位数在2,3中选,如何选?同样的,把k的范围进一步缩小,缩小到是 1 < = k < = 1 1<=k<=1 1<=k<=1或者 2 < = k < = 2 2<=k<=2 2<=k<=2。问题来了,如何在代码中体现这种范围的缩小过程呢?我总不能写一大堆判定语句吧?下图详细地给出了如何判断第 i i i位的数字:
在这里插入图片描述
剩下的就是取商,判断位置,然后更新更准确的位置,然后取商…

Java代码

    public String getPermutation(int n, int k) {
        StringBuilder sb = new StringBuilder();
        List<Integer> list = new LinkedList();
        int sum = 1;
        int i=1;
        for(i=1;i<=n;i++){
            sum*=i;
            list.add(i);
        }
        i=i-1;
        while(i>0){
            sum = sum/i;
            int temp = k/sum;
            if(temp*sum==k) {
                sb.append(list.get(temp-1));
                list.remove(temp-1);
                temp = temp-1;
            }
            else {
            	sb.append(list.get(temp));
            	list.remove(temp);
            	}
            k = k - temp*sum;
            i--;
        }
        return sb.toString();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值