(上一个排列问题)给定一个由 $1 \sim n$构成的排列 $a$,求 $a$ 的上一个排列。
比如,当 $n$ 等于 $3$ 时,由 $1 \sim 3$ 构成的全排列按照从小到大排如下所示:
```
1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
```
其中,排列 `3,2,1` 的上一个排列为 `3,1,2`;排列 `3,1,2` 的上一个排列为 `2,3,1`;排列 `2,3,1` 的上一个排列为 `2,1,3`;排列 `2,1,3` 的上一个排列为 `1,3,2`;排列 `1,3,2`的上一个排列为 `1,2,3`;排列 `1,2,3` 没有上一个排列。
你的任务是根据输入的排列计算并输出其上一个排列;
特别地,若输入的排列没有上一个排列,输出 `-1`。
试补全下面的模拟上一个排列的程序。
1 #include <iostream>
2 #include <algorithm>
3 using namespace std;
4 int n, a[1000];
5 bool cmp(int a, int b) {
6 return ___(1)___ ;
7 }
8 bool pre_permutation(int a[], int n) {
9 int i = n-1;
10 while (i > 0 && a[i-1] < a[i])
11 i--;
12 if ( ___(2)___ )
13 return false;
14 for (int j = i; j < n; j++) {
15 if (j == n-1 || ___(3)___ ) {
16 swap( ___(4)___ , a[j]);
17 break;
18 }
19 }
20 sort( ___(5)___ , a+n, cmp);
21 return true;
22 }
23 int main() {
24 cin >> n;
25 for (int i = 0; i < n; i++)
26 cin >> a[i];
27 if (pre_permutation(a, n)) {
28 for (int i = 0; i < n; i++)
29 cout << a[i] << " ";
30 }
31 else {
32 cout << -1 << endl;
33 }
34 return 0;
35 }
通过分析问题代码,可得本题的思路是先找到满足 $a[i-1] > a[i]$ 的最小的下标 $i$,然后从 $a[i]$ 到 $a[n-1]$ 中找到最大的满足 $a[j] < a[i-1]$ 的 $a[j]$,并将 $a[i-1]$ 与 $a[j]$ 交换,然后对 $a[i] \sim a[n-1]$ 从大到小排序,即实现求解 $a$ 的上一个排列。
1. B。通过上面的分析可得 $cmp$ 函数想要实现的效果是 `从大到小排`,所以函数将返回 $a > b$。
2. A。若循环结束时 $i$ 的值为 $0$,说明序列是升序的,一个升序的排列本身就是最小的排列,没有上一个排列。
3. C。因为 $a[i]$ 到 $a[n-1]$ 是升序的,且 $a[i] < a[i-1]$,所以从 $i$ 到 $n-1$ 找到最后一个满足 $a[j] < a[i-1]$ 的 $a[j]$ 即为要交换的那个数,且 $a[j+1] > a[i-1]$。
4. B。需要将 $a[i]$ 到 $a[n-1]$ 中最大的那个 $< a[i-1]$ 的数(即 $a[j]$)找出来与 $a[i-1]$ 交换,所以是将 $a[i-1]$ 与 $a[j]$ 进行交换。
5. C。需要将 $a[i]$ 到 $a[n-1]$ 从大到小排序。