原题: https://www.patest.cn/contests/pat-b-practise/1045
思路: 看样子乙级最后一道题, 如果复杂度是n^2, 基本上是错了, 不错
也是超时的节奏, 一开始自己的想法复杂了.
我们直接先看题目给出的测试
输入样例:
5
1 3 2 4 5
输出样例:
3
1 4 5
要想确定某一个数是不是主元, 就是要确定这个数左边的值都比当前数小,
而右边的值都比当前数大(这不是废话吗!)
假如我们另外有2个数组, 和当前数组一一对应, 分别存放的是当前数左边
最大值和当前数右边最小值, 这样简单作下比较就OK了.
我们看下给出的测试, 首先1的左边没有数, 可能大家愿意认为1的左边最
小数是0, 右边最大数是2. 这样 0 1 2, 1就是我们需要的主元. 但是我
们现在不这样想, 我们把1本身也给考虑进去, (这样主要是为了编程方便)
把自身也考虑进去, 那么1左边最大的数就是1, 1右边最小的数还是1, 对应
上面的测试样例, 我们需要这样的数组
原来的: 1 3 2 4 5
左边的: 1 3 3 4 5
右边的: 1 2 2 4 5
没错, 你会发现如果当前数是主元, 那它就是和左右都相等. 最后最关键的
问题就是怎么得出这2个数组了, 自己在纸上思考下, 或者看看下面的代码,
相信你已经会写了.
坑1: 如果所有的数都不是主元, 输入2行, 分别是0
和
实现:
#include <stdio.h>
int main (void) {
int n;
int arr[100010];
int lmax[100010];
int rmin[100010];
int count = 0;
int max;
int min;
int i;
char ch = ' ';
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// 从左边开始, 一步步找当前数左边的最大数
max = arr[0]; // 初始最大数
for (i = 0; i < n; i++) {
if (arr[i] > max) {
max = arr[i];
}
lmax[i] = max;
}
// 从右边开始, 一步步找当前数右边的最小数
min = arr[n - 1]; // 初始最小数
for (i = n - 1; i >= 0; i--) {
if (arr[i] < min) {
min = arr[i];
}
rmin[i] = min;
}
// 接下来打印也要废些功夫, 首先遍历把主元数出来,
// 并且把非主元标记为0
for (i = 0; i < n; i++) {
if (arr[i] == lmax[i] && arr[i] == rmin[i]) {
count++;
} else {
arr[i] = 0;
}
}
printf("%d
", count);
// 接着利用count, 控制打印格式
// 注意空在C语言中对应着
for (i = 0; i < n && count != 0; i++) {
if (count == 1) ch = ' ';
if (arr[i] != 0) {
printf("%d%c", arr[i], ch);
count--;
}
}
printf("
");
return 0;
}