目录
🎬 攻城狮7号:个人主页
🔥 个人专栏: 《C/C++算法》
⛺️ 君子慎独!
🌈 大家好,欢迎来访我的博客!
⛳️ 此篇文章主要讲解算法题目:解排列序列
📚 本期文章收录在《C/C++算法》,大家有兴趣可以自行查看!
⛺️ 欢迎各位 ✔️ 点赞 👍 收藏 ⭐留言 📝!
一、题目
给出集合 [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` 个元素的排列,每个位置上的数字选择是固定的。
- 第 `k` 个排列可以通过数学计算直接构造,而不需要生成所有排列。
具体步骤
(1)**计算阶乘**:
- 预先计算 `1` 到 `n-1` 的阶乘,用于确定每个位置上的数字。
- 例如,`n = 4` 时,阶乘为 `[1, 2, 6, 24]`。
(2)**确定每个位置上的数字**:
- 从最高位开始,依次确定每个位置上的数字。
- 对于第 `i` 位,计算 `k / (n-i)!`,得到当前数字在剩余数字中的索引。
- 将选中的数字从剩余数字中移除,并更新 `k` 为 `k % (n-i)!`。
(3)**构造排列**:
- 将选中的数字按顺序拼接成最终的排列。
三、代码实现
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
// 返回第k个排列
string getPermutation(int n, int k) {
// 计算阶乘并存储,方便后续计算排列的索引
vector<int> factorial(n, 1);
for (int i = 1; i < n; ++i) {
factorial[i] = factorial[i - 1] * i;
}
// 初始化数字列表,这些数字将用于构建排列
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
nums[i] = i + 1; // 填充从1到n的数字
}
// 将k减1以转换为基于0的索引
--k;
string result; // 用于存储最终排列的字符串
// 构建排列
for (int i = n - 1; i >= 0; --i) {
// 计算当前位置的数字索引
int index = k / factorial[i];
// 将数字添加到结果字符串
result += to_string(nums[index]);
// 从列表中移除已经使用的数字
nums.erase(nums.begin() + index);
// 更新k值,为下一个位置的数字计算索引
k %= factorial[i];
}
return result; // 返回最终排列
}
};
int main() {
Solution solution;
int n, k;
// 示例
n = 3; // n表示排列中的数字范围是1到n
k = 3; // k表示我们要找的是第k个排列
// 输出第k个排列
cout << "n = " << n << ", k = " << k << " 的排列是: " << solution.getPermutation(n, k) << endl;
return 0;
}
复杂度分析
- **时间复杂度**:`O(n^2)`,其中 `n` 是数字的个数。每次移除数字的时间复杂度为 `O(n)`。
- **空间复杂度**:`O(n)`,用于存储阶乘和可用数字。
通过数学规律直接构造第 `k` 个排列,避免了生成所有排列的高复杂度。这种方法高效且易于实现,适合解决类似问题。
看到这里了还不给博主点一个:
⛳️ 点赞
☀️收藏
⭐️ 关注
!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
再次感谢大家的支持!
你们的点赞就是博主更新最大的动力!