代码
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int a[n] = {0};
for(int i=0; i<n; i++) {
scanf("%d", &a[i]);
}
int leftMax[n] = {0};
int rightMin[n] = {0};
for(int i=1; i<n; i++) {
if(a[i]>leftMax[i-1]) {
leftMax[i] = a[i];
} else {
leftMax[i] = leftMax[i-1];
}
}
rightMin[n-1] = a[n-1];
for(int i=n-2; i>=0; i--) {
if(a[i]<rightMin[i+1]) {
rightMin[i] = a[i];
} else {
rightMin[i] = rightMin[i+1];
}
}
int b[n] = {0};
int count = 0;
for(int i=0; i<n; i++) {
bool flag = true;
if(i==0) {
if(a[i]>rightMin[i+1]) {
flag = false;
}
} else if(i==n-1) {
if(a[i]<leftMax[i-1]) {
flag = false;
}
} else {
if(a[i]<leftMax[i-1] || a[i]>rightMin[i+1]) {
flag = false;
}
}
if(flag) {
b[count++] = a[i];
}
}
printf("%d\n", count);
if(count>0) {
printf("%d", b[0]);
for(int i=1; i<count; i++) {
printf(" %d", b[i]);
}
}
printf("\n");
return 0;
}
注解
1、即使count=0,第二行也要输出一个空行,而不能什么都不输出。所以把printf("\n")单独放在了外面。否则会有一个case是格式错误。
2、如果线性找,会有三个案例超时。
此题的优化方法:打表,扫描一遍把所有数字左侧的最大值和右侧的最小值全部扫描出来。好处是只需要扫描一遍,对所有案例均适用。否则,来一个案例就要扫描一遍,浪费很多时间。代码:
int leftMax[n] = {0};
int rightMin[n] = {0};
for(int i=1; i<n; i++) {
if(a[i]>leftMax[i-1]) {
leftMax[i] = a[i];
} else {
leftMax[i] = leftMax[i-1];
}
}
rightMin[n-1] = a[n-1];
for(int i=n-2; i>=0; i--) {
if(a[i]<rightMin[i+1]) {
rightMin[i] = a[i];
} else {
rightMin[i] = rightMin[i+1];
}
}