本题计算一个字符串的第M个全排列,组合数学中计算一个字符串的下一个全排列的算法如下:
- 从尾部开始往前寻找两个相邻的元素,前一个元素为 i,后一个元素为 j,且 i<j;
- 从后往前找第一个大于 i 的元素 k,将第 i、k 个元素对调;
- [j,last] 范围的元素倒转(颠倒排列)。
使用上述的全排列算法,AC代码如下:
#include <iostream>
using namespace std;
void fullPermutation(int arr[], int n); //计算字符串的下一个全排列
int main()
{
int N, M;
int arr[1010];
while (cin >> N >> M)
{
memset(arr, 0, sizeof(arr));
for (int i = 1; i <= N; i++)
arr[i] = i;
M--; //字符串的第一个全排列为其自身
while (M--) //计算第M个全排列
fullPermutation(arr, N);
cout << arr[1];
for (int i = 2; i <= N; i++)
cout << " " << arr[i];
cout << endl;
}
return 0;
}
void fullPermutation(int arr[], int n) //计算字符串的下一个全排列
{
int i;
for (i = n - 1; i > 0; i--) //从尾部开始往前寻找两个相邻的元素,前一个元素为 i,后一个元素为 j,且 i<j
{
if (arr[i] < arr[i + 1])
break;
}
for (int j = n; j > 0; j--) //从后往前找第一个大于 i 的元素 k,将第 i、k 个元素对调
{
if (arr[j] > arr[i])
{
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
break;
}
}
int mid = (i + n) / 2;
for (int k = i + 1; k <= mid; k++) // [j, last] 范围的元素倒转(颠倒排列)
{
int temp = arr[k];
arr[k] = arr[n - k + i + 1];
arr[n - k + i + 1] = temp;
}
}
C++ STL有一个函数 next_permutation 专门计算字符串的下一个全排列,AC代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N, M;
int arr[1010];
while (cin >> N >> M)
{
memset(arr, 0, sizeof(arr));
for (int i = 1; i <= N; i++)
arr[i] = i;
M--; //字符串的第一个全排列为其自身
while (M--) //计算第M个全排列
next_permutation(arr + 1, arr + N + 1);
cout << arr[1];
for (int i = 2; i <= N; i++)
cout << " " << arr[i];
cout << endl;
}
return 0;
}
继续加油。
本文介绍了一种计算字符串第M个全排列的方法,包括手动实现的全排列算法和利用C++ STL中的next_permutation函数。通过具体示例代码展示了如何找到字符串的下一个全排列,最终达到目标全排列。
319

被折叠的 条评论
为什么被折叠?



