LeetCode排列序列

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence
给出集合 [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”
示例 3:
输入:n = 3, k = 1
输出:“123”
提示:
1 <= n <= 9
1 <= k <= n!

思路:暴力肯定是有点问题的,一个位一个位枚举超时。
正解:其实每一个位是可以算出来的。比如n=4,k=9的时候。
先写出来所有的
1234
1243
1324
1342
1423
1432
2134
2143
2314
枚举每一位当前的可能,最多有n种情况。如果当前的第一位是2,那么是不是就可以直接减去第一位是1的情况,有多少情况,就是(n - 1)!,即后面的数的全排列。所以找个数组直接算出来(n)!,然后按照上面的方法来计算即可。
手动模拟一下,假设第一位是1,不用减(从头开始),假设第一位是2,第一位是1的情况是满足的(9>6),也就是可以直接跳过1,但不能跳过2,因为6+6>9所以第一位是2,减去第一位是1的个数9-6=3.再看第二位。第二位是1,则后面两位有2种情况,3 > 2满足。跳过1(此时注意第二位不能是2了,前面已经有过了。)此时是3的话,是不能跳过的,因为2+2>3.故第二位是3.此时还剩1,那么1就不能跳过了。就是1.最后剩个4,直接加入。

多试试几个样例就可以发现其中的解法,就是小细节比较多。

class Solution {
public:
    int a[12]; 
    bool f[12];
    string s1;
    int i, j, num, ans, shu;
    string getPermutation(int n, int k) {
        a[0] = 1;
        for (i = 1; i <= n; i++){
            a[i] = a[i - 1] * i;
        }
        while (s1.size() + 1 < n){
             //num = 0;
             for (i = 1; i <= n; i++){
                 if (f[i]) continue;//前面出现过了
                 num += a[n - s1.size() - 1];//加上跳过这次的个数
                 if (num >= k){
                     k -= ans;//此时减去的是不跳过这次的个数
                     s1 += to_string(i);
                     f[i] = true;
                     num = 0;
                     ans = 0;//下次有可能一次也不跳过,那就是0,特殊注意
                     break;
                 }
                 ans = num; 
             }
        }
        for (i = 1; i <= n; i++)
          if (f[i] == false) s1 += to_string(i);//剩余最后一个
       return s1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值