1045クイックソート(25点)
プロセスの古典的な分割の有名な高速ソートアルゴリズム:我々は通常、いくつかの方法が主エレメントよりも大きなドルに、その左側に少ない主エレメントよりも、交換により、主成分として元の要素をとる使用しますそれはそうです。所定の分割後の互いに異なるnは正の整数の配列は、PCA Iは、予め選択さに分割することができるどのように多くの要素を求めることができますか?
例えば、与えられました
、配置が1,3,2,4,5です。その後:
;、それはPCAかもしれないので、それは、大きいよりも右側の素子を1ない要素を残していない
ことが主成分であることができないので、2時間より左側が小さい場合よりも素子3が、その右が;
ただしそれは大規模な素子2,3の右側にあるが、それは主要な要素ではないので、それは、その左側より大きいものよりも、
同様の理由は、図4及び図5は、主要素である可能性が高いです。
従って、3つの要素は、主成分分析であってもよいです。
入力フォーマット:
nは整数(電源の≤105)任意の正の入力ライン1において、線2は、空間N個の異なる正の整数、以下10 ^ 9の数で分離されます。
出力フォーマット:
最初の行では、主要な要素の可能な出力素子の数であり、システム内の2行目のこれらの要素の昇順で出力が、ラインが余分なスペースを含めを持っていない可能性があり、スペースで区切られました。
サンプル入力:
5
1つの2 4 3 5。
出力サンプル:
3
1 4 5。
分析:
直接彼の前にすべての要素を持つ各要素の比較や背後明らかにタイムアウト、我々は、各要素の特性の主成分を使用することができます以下のマークの最小の要素よりも前後で最大の要素よりも大きくなると、彼はPCAことができると思っていました。
コード:
#include <stdio.h>
#include <algorithm>
#include <vector>
#define N 100000 + 10
using namespace std;
int data[N]; // data用来存储输入的N个正整数
int left_flag[N];// 用来标记数组中的每个元素是否大于它左边的所有元素
int righ_flag[N];// 用来标记数组中的每个元素是否小于它右边的所有元素
int main(){
int n;
scanf("%d", &n);
for(int i=0; i<n; ++i){
scanf("%d", &data[i]);
}
int left_max = 0;// 由于输入的是N个不同的正整数,所以left_max初值设置为0即可
for(int i=0; i<n; ++i){
if (data[i] > left_max){// 如果当前元素大于左边所有元素的最大值,也就是说当前元素大于它左边的所有元素
left_max = data[i];// 更新一下最大值
left_flag[i] = 1;// 标记一下这个元素
}
}
int righ_min = 1000000000 + 1;// 由于输入的N个整数都不超过10^9,所以righ_min初值设置为10^9 + 1
for(int i=n-1; i>=0; --i){
if(data[i] < righ_min){// 如果当前元素小于右边所有元素的最小值,也就是说当前元素小于它右边的所有元素
righ_min = data[i];// 更新一下最大值
righ_flag[i] = 1;// 标记一下这个元素
}
}
vector<int> answer;
for(int i=0; i<n; ++i){
if(left_flag[i] == 1 && righ_flag[i] == 1){//如果它既大于左边的所有元素又小于右边的所有元素
answer.push_back(data[i]);
}
}
sort(answer.begin(), answer.end());// 把所有可能的主元排一下序
int count = answer.size();
printf("%d\n", count);// 输出有多少个主元
if(count == 1){
printf("%d\n", answer[answer.size()-1]);// 如果只有一个,直接输出并且换行
}else if(count > 1){
for(int i=0; i<answer.size()-1; ++i){
printf("%d ", answer[i]);
}
printf("%d\n", answer[answer.size()-1]);
}else{
printf("\n");// 本题的一个坑,没有主元的时候需要单独输出一个换行。
}
return 0;
}