题目大意:
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。
给定划分后的 N 个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?
以快速排序引出,其实与快排没有关系。
给定序列,包含N个正整数,如果一个属左边的所有数都比它小,右边的所有数都比它大,则成该数为主元,求序列中主元的个数。
思路:
1)直接暴力求解会超时。
2)假设序列为A,定义数组leftMax.记录序列A的每一位左边的最大值(不含本位),即leftMax[i]记录了A[0]-A[i]的最大值,显然可以令leftMax[0]=0,
从左至右遍历A,left[i-1]记录A[0]-A[i-2]的最大值,与A[i-1]相比,决定leftMax[i]的取值
3)同理,定义数组rightMin记录A的每一位右边的最小数,令rightMin[i]记录A[i+1]-A[n-1]的最小值,操作同上。
4)遍历A,如果第i个元素大于leftMax[i],小于rightMin[i],则该数为一个主元,输出。
AC代码:
//PAT_A 1101
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
const int INF = 0x3fffffff;
int a[maxn], leftMax[maxn], rightMin[maxn];
int ans[maxn], num = 0;
int main() {
int n;
(void)scanf("%d", &n);
for (int i = 0; i < n; i++) {
(void)scanf("%d", &a[i]);
}
leftMax[0] = 0, rightMin[n - 1] = INF;
for (int i = 1; i < n; i++) {
leftMax[i] = max(leftMax[i - 1], a[i - 1]);//leftMax[i-1]存了前i-2个数中最大的数
}
for (int i = n - 2; i >= 0; i--) {
rightMin[i] = min(rightMin[i + 1], a[i + 1]);//
}
for (int i = 0; i < n; i++) {
if (leftMax[i]<a[i] && rightMin[i]>a[i])ans[num++] = a[i];
}
printf("%d\n", num);
for (int i = 0; i < num; i++) {
printf("%d", ans[i]);
if (i < num - 1)printf(" ");
}
printf("\n");
return 0;
}
来源:CSDN
作者:学姐你好高冷
链接:https://blog.csdn.net/weixin_44699689/article/details/104259914