[PAT-A 1101]Quick Sort

霸气de小男生 提交于 2020-02-12 11:49:15

在这里插入图片描述
在这里插入图片描述

题目大意:
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。
给定划分后的 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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!