飞燕之家上的一道排序题:
题目描述:
某市重点高中很有名气,它在计算录取分数线的时候,
采用以下办法:总人数乘以录取百分比,得到录取人数k后,
从最高分开始数k个人,这个人的中考分数就作为
这所学校的录取分数线了。
输入:
有多个测试点,每个测试点第一行是n和k(k<=n),
n是总人数,总人数不超过1e6,k是录取的人数
第二行就是n个学生的中考分数,由于采用一种
特殊的标准计分方式,分数范围在0至1e8
输出:
对每个测试点输出对应的分数线,一个结果一行
样例输入:
7 3
1 2 3 4 5 6 7
样例输出:
5
最开始用插入,第三组用例超时:
1
#include <iostream>
2
using namespace std;
3
int main()
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
5
unsigned int numTotal,numEnroll;
6
while(EOF!=scanf("%u %u",&numTotal,&numEnroll) && numTotal!=0 && numEnroll!=0)
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
8
unsigned int * pdataDes=new unsigned int[numEnroll];
9
unsigned int * pdataSrc=new unsigned int[numTotal];
10
memset(pdataDes,(unsigned int)0,numEnroll*sizeof(unsigned int));
11
for(int i=0;i<numTotal;i++)
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
scanf("%u",&pdataSrc[i]);
14
}
15
for(int i=0;i<numTotal;i++)
16![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
17
for(int j=0;j<numEnroll;j++)
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
if(pdataSrc[i]>pdataDes[j])
20![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
21
for(int k=numEnroll-1;k>j;k--)
22
pdataDes[k]=pdataDes[k-1];
23
pdataDes[j]=pdataSrc[i];
24
break;
25
}
26
}
27
}
28
printf("%u\n",pdataDes[numEnroll-1]);
29
memset(pdataDes,0,numEnroll*sizeof(unsigned int));
30
delete [] pdataDes;
31
delete [] pdataSrc;
32
}
33
return 0;
34
}
结果:
Test 1: Accepted Time = 0 ms
Test 2: Accepted Time = 48 ms
Test 3: Time Limit Exceed
--------------------------------
Problem ID ct8_2
Test Result Time Limit Exceed
Time Limit 5000 ms
Total Memory 5416 Kb / 65000 Kb
Code Length 1066 Bytes
后来改为统计第n大的数,直接输出。。本以为减少了内存读写操作能好些,结果第二组用例居然更慢了。。。
1
#include <iostream>
2
using namespace std;
3
int main()
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
5
unsigned int numEnroll,numTotal,temp,curMax;
6
while(EOF!=scanf("%u %u",&numTotal,&numEnroll))
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
8
unsigned int * pdata=new unsigned int[numTotal];
9
memset(pdata,0,numEnroll*sizeof(unsigned int));
10
unsigned int i;
11
for(i=0;i<numTotal;i++)
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
scanf("%u",&pdata[i]);
14
}
15
i=0;
16
17
unsigned int count=1;
18
while(count<=numEnroll)
19![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
20
int flag=0;
21
curMax=0;
22
for(int j=0;j<numTotal;j++)
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
24
if(curMax<pdata[j])
25![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
26
flag=j;
27
curMax=pdata[j];
28
}
29
}
30
pdata[flag]=0;
31
count++;
32
}
33
printf("%u\n",curMax);
34
delete [] pdata;
35
}
36
return 0;
37
}
38![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
结果:
Test 1: Accepted Time = 0 ms
Test 2: Accepted Time = 68 ms
Test 3: Time Limit Exceed
--------------------------------
Problem ID ct8_2
Test Result Time Limit Exceed
Time Limit 5000 ms
Total Memory 4000 Kb / 65000 Kb
Code Length 905 Bytes
后来改为快速排序,这回快了一些,但是第四组用例仍然超时:
1
#include <iostream>
2
using namespace std;
3
#define max 1000000
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
int pdata[max]=
{0};
5
void swap(int *a,int *b)
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
7
int temp=*a;
8
*a=*b;
9
*b=temp;
10
}
11
int partition(int *a,int begin,int end)
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
13
int i=begin-1;
14
for(int j=begin;j<end;j++)
15![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
16
if(a[j]<=a[end])
17![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
18
i+=1;
19
swap(&a[i],&a[j]);
20
}
21
}
22
swap(&a[i+1],&a[end]);
23
return i+1;
24
}
25
void myqsort(int *a,int begin,int end)
26![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
27
if(begin<end)
28![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
int i=partition(a,begin,end);
30
myqsort(a,begin,i-1);
31
myqsort(a,i+1,end);
32
}
33
}
34
int main()
35![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
36
int numTotal,numEnroll;
37
while(EOF!=scanf("%u %u",&numTotal,&numEnroll))
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
39
//int *pdata = new int [numTotal];
40
memset(pdata,0,numTotal*sizeof(int));
41
for(int i=0;i<numTotal;i++)
42
scanf("%u",&pdata[i]);
43
myqsort(pdata,0,numTotal-1);
44
printf("%u\n",pdata[numTotal-numEnroll]);
45
//delete [] pdata;
46
}
47
return 0;
48
}
结果:
Test 1: Accepted Time = 0 ms
Test 2: Accepted Time = 26 ms
Test 3: Accepted Time = 4246 ms
Test 4: Time Limit Exceed
--------------------------------
Problem ID ct8_2
Test Result Time Limit Exceed
Time Limit 5000 ms
Total Memory 4032 Kb / 65000 Kb
Code Length 934 Bytes
由于快速排序导致大量递归浪费时间空间,所以考虑要减少递归次数。由于要找第n大的数,所以没有必要对所有数据都排序,又找到了快速选择算法。。
1
#include <iostream>
2
#include <ctime>
3
using namespace std;
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
int pdata[1000000]=
{0};
5
void swap(int *a, int *b)
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
7
int temp=*a;
8
*a=*b;
9
*b=temp;
10
}
11
int partition(int *a, int begin, int end)
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
13
swap(&a[rand()%(end-begin+1)],&a[end]);
14
int i=begin-1;
15
for(int j=0;j<end;j++)
16![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
17
if(a[j]<=a[end])
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
i++;
20
swap(&a[i],&a[j]);
21
}
22
}
23
swap(&a[i+1],&a[end]);
24
return i+1;
25
}
26
int qksel(int *a, int n, int begin, int end)
27![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
28
int temp=partition(a,begin,end);
29
if(n==temp)return a[temp];
30
else if(n<temp) return qksel(a,n,begin,temp-1);
31
else return qksel(a+temp+1,n-temp-1,0,end-temp-1);
32
}
33
int main()
34![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
35
srand((unsigned int)time(NULL));
36
int numTotal,numEnroll;
37
while(EOF!=scanf("%d %d",&numTotal,&numEnroll))
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
39
for(int i=0;i<numTotal;i++)
40
scanf("%d",&pdata[i]);
41
int temp=qksel(pdata,numTotal-numEnroll,0,numTotal-1);
42
printf("%d\n",temp);
43
}
44
return 0;
45
}
终于。。。。
Test 1: Accepted Time = 0 ms
Test 2: Accepted Time = 21 ms
Test 3: Accepted Time = 3187 ms
Test 4: Accepted Time = 3248 ms
--------------------------------
Problem ID ct8_2
Test Result Accepted
Total Time 6456 ms
Total Memory 4032 Kb / 65000 Kb
Code Length 1030 Bytes
后记:这题做了整整两天提交了n多次,没心思再细抠了。。
快速选择算法描述是看老外写的,看得不一定明白。。链接如下
http://www.ics.uci.edu/~eppstein/161/960125.html
也不知道是不是这么回事,
另外看别人提交的答案有个强悍的家伙四组用例一共才用不到1500ms,
我这个排序写得肯定很傻很天真,请高手指出问题,我爱你们