共42道题,当前是第34

Description

(上一个排列问题)给定一个由 $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]$ 从大到小排序。

Question

___ (1) ___ 处应填( )

___ (2) ___ 处应填( )

___ (3) ___ 处应填( )

___ (4) ___ 处应填( )

___ (5) ___ 处应填( )

陈伦制作 版权所无 粤ICP备16127491号-1