1101 Quick Sort (25 分)
题目大意
题目大意:快速排序中,我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的N个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?例如给定N = 5, 排列是1、3、2、4、5。则:
1的左边没有元素,右边的元素都比它大,所以它可能是主元;
尽管3的左边元素都比它小,但是它右边的2它小,所以它不能是主元;
尽管2的右边元素都比它大,但其左边的3比它大,所以它不能是主元;
类似原因,4和5都可能是主元。
因此,有3个元素可能是主元。
给N个数,第一行输出可能是主元的个数,第二行输出这些元素。
基本思路
数据结构:
设置两个数组a、b,同时接收测试样例,并且将数组a按递增顺序排好序。
定义数组v,按顺序记录可能是主元的元素。(cnt既统计主元个数,又作为数组v的下标)
定义变量max,实时记录当前元素左边所有元素中的最大值。
核心思路:
枚举i从0到n-1:
如果a[i]==b[i]&&b[i]>max,说明b[i]左边的元素都比b[i]小,b[i]右边的元素都比b[i]大,说明当前元素b[i]可以作为主元。
如果b[i]>max,则更新max
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100010;
int n;
int main(){
cin>>n;
vector<int> a(n),b(n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(a.begin(),a.end());//对数组a进行排序
int v[MAXN];//存放主元
int cnt=0;//记录主元的个数同时也作为数组v的下标
int max=0;//当前元素b[i]左边所有元素中的最大值
for(int i=0;i<n;i++){
//如果a[i]等于b[i]并且b[i]比左边所有元素中的最大值还要大,那它就是一个主元,把它放入数组v
if(a[i]==b[i]&&b[i]>max){
v[cnt++]=b[i];
}
//如果b[i]比左边所有元素中的最大值还要大,则更新最大值
if(b[i]>max){
max=b[i];
}
}
//输出主元个数
printf("%d\n", cnt);
//按顺序输出可能是主元的元素,即数组v
for(int i = 0; i < cnt; i++) {
if (i != 0) printf(" ");
printf("%d", v[i]);
}
printf("\n");
}