emmm,讲道理其实这道题感觉还是蛮简单的,但是通过率只有0.17着实把老身吓了一跳
附上井同学的连接https://blog.csdn.net/jyfbug/article/details/80044006
哦,突然发现一个bug,好像不用快速排序的,因为主元就是排好顺序的,感谢井同学的提醒,阿里嘎多~
其实这道题目思路还是很清晰的,嗯嗯,接下来是本戏精的show time
-----------------------------------------啦啦啦,我是题目的分割线-----------------------------------------
题目:著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。给定划分后的N个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?
例如给定N = 5, 排列是1、3、2、4、5。则:
1的左边没有元素,右边的元素都比它大,所以它可能是主元;尽管3的左边元素都比它小,但是它右边的2它小,所以它不能是主元;
尽管2的右边元素都比它大,但其左边的3比它大,所以它不能是主元;
类似原因,4和5都可能是主元。
因此,有3个元素可能是主元。
输入格式:
输入在第1行中给出一个正整数N(<= 105);第2行是空格分隔的N个不同的正整数,每个数不超过109。
输出格式:
在第1行中输出有可能是主元的元素个数;在第2行中按递增顺序输出这些元素,其间以1个空格分隔,行末不得有多余空格。
输入样例:5 1 3 2 4 5输出样例:
3 1 4 5
---------------------------------------啦啦啦,我是思路的分割线-------------------------------------------
思路:emmm,最主要就分成四步吧,首先输入到num数组,然后找主元,整理排序,最后输出...是不是太简单了
ou,因为找主元最主要的思路就是遍历所有元素,分别与该元素左边最小的值,和该元素右边最大的值进行比较
可以看出,当前元素比左侧最大值小,所以它不是主元,主元的要求是:比左侧最大值要大,比右侧最小值要小;
并且最好时间复杂度要降到最低,就是说最好是一次循环就够了;
那么左侧最大值可以根据当前元素遍历的时候更改,但是右侧最小值不可以呀,因为就算你第一次找到了右侧最小值,当当前元素移动到右侧最小值右侧的时候,右侧最小值是要改变的,就变成了右侧第二小的值,那么怎么办呢,嗯,其实可以用一个数组存储右侧最小值:
我们在找主元这次遍历之前从右侧开始遍历数组num,设置right_min数组第一个元素为1000000000(这是题目的数值限制),然后从右往左遍历num数组,如果num数组中的元素比right_min数组前一个元素要小,就插入到right_min数组中;
整理之后得到right_min数组为(num中第一个数据不参与比较)
当right_min数组建立完毕后,我们就可以开始比较啦~
要注意,right_min数组是从右往左比较的,如果num当前元素的下一个元素==right_min数组中的值,那么right_min数组往左挪一个(为什么当前元素不可能等于right_min数组中的值呢?因为num中第一个数据不参与比较,所以右侧最小值永远不可能等于当前元素的值)
嗯,可能我讲得不是很清楚,那就献上代码~~~
-----------------------------------------啦啦啦,我是代码的分割线--------------------------------------------
代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int N;
int num[100000];
int left_max=0;//记录左侧最大值
int right_min[100000];//记录右侧最小值
int right_count=0;//记录右侧最小值的位置
scanf("%d",&N);
int i=0;
for(i;i<N;i++)
{
scanf("%d",&num[i]);
}
/*从num数组右侧开始找
如果比前一个right_min小
就插入right_min数组
在遍历num数组的时候
如果num数组中的数不等于right_min中的数
那么right_min当前的数一定是右侧最小的数*/
right_min[right_count]=1000000000;//每个数不超过10的9次方
right_count++;
for(i=N-1;i>0;i--)
{
//num[0]不记录进去
if(num[i]<right_min[right_count-1])
{
right_min[right_count]=num[i];
right_count++;
}
}
//遍历num数组,找出主元
int main_ele[100000];
int main_count=0;
int temp=right_count-1;
for(i=0;i<N;i++)
{
if(num[i]>left_max&&num[i]<right_min[temp])
{
//整数各不相同
left_max=num[i];
main_ele[main_count]=num[i];
main_count++;
}
else if(num[i]>left_max)
{
left_max=num[i];
}
if(num[i+1]==right_min[temp])
{
/*因为永远是跟当前num右侧数的最小值进行比较
所以是num[i+1]*/
if(temp!=0)temp--;
}
}
printf("%d\n",main_count);
for(i=0;i<main_count-1;i++) printf("%d ",main_ele[i]);
//如果没有主元元素就输出一个空行,不要问我为什么这样QAQ
if(main_count==0)printf("\n");
else printf("%d",main_ele[i]);
return 0;
}