60. 第k个排列(回溯)

本文介绍了一种算法问题,即如何在给定整数n和k的情况下,找到由1到n组成的全排列中的第k个排列。提供了两种解决方法,一种是通过递归生成所有可能的排列并计数,效率较低;另一种是利用数学规律直接计算,效率较高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

法一:

用一个计数器,表示求到的是第i个排列,从头开始求排列,当i等于k时,表示找到的是第i个排列,就返回

效率:低

class Solution {
public:
    string get(int &count, string &temp, int loc, vector<bool> &is_visit, int k) {
        string res;
        if (loc == is_visit.size()) {
            count++;
            if (count == k) {
                res = temp;
                return res;
            }
            return res;
        }
        for (int i = 0; i < is_visit.size(); ++i) {
            if (is_visit[i] == false) {
                temp[loc] = '1'+i;
                is_visit[i] = true;
                string t = get(count, temp, loc+1, is_visit, k);
                is_visit[i] = false;
                if (!t.empty())
                    return t;
            }
        }
        return res;
    }
    string getPermutation(int n, int k) {
        string temp;
        temp.resize(n);
        vector<bool> is_visit(n, false);
        int count = 0;
        return get(count, temp, 0, is_visit, k);
    }
};

法二:按规律直接计算下标

效率:很高

class Solution {
public:
    string getPermutation(int n, int k) {
        vector<int> factorial(9);
        factorial[0] = 1;
        for (int i = 1; i < factorial.size(); ++i) {
            factorial[i] = factorial[i-1] *(i);
        }
        k--;
        string num = "123456789";
        string res;
        while (n--) {
            int num_loc = k/factorial[n];
            res += num[num_loc];
            k %= factorial[n];
            num.erase(num_loc,1);
        }
        return res;
    }
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值