Fork me on GitHub

PAT(甲级)渡劫(十七)-Stack(30)


PAT(甲级)渡劫(十七)-Stack(30)

题目大意:

题意:有三种操作,分别是
1.Push key:将key压入stack
2.Pop:将栈顶元素取出栈
3.PeekMedian:返回stack中第(n+1)/2个小的数(中位数)

算法思想:

分桶法的基本思路是分治,在一开始的暴力解法中,我们可以认为Count数组是一个大的桶,这个大的桶里有510^5个小桶,每个小桶能装一个数,在分桶法中,我们建立多个大桶,每个桶中又有小桶,比如,我们建立多个500个大桶,每个桶的容量是100,同时记录每个大桶中存放的数据的个数,在查找的时候我们可以通过每个大桶中元素的快速定位到放置中位数的那个小桶。当然你可以认为这是一种HASH,hash(key) = key/10。设每个大桶中含有k个小桶,共有m个大桶,mk = n为定值。则一开始我们需要遍历大小为m的大桶数组,后来要遍历大小为k的单个大桶,时间复杂度为O(max(k,m))在nk为定值的情况下,易知m = k = (mk)^(1/2)的时候效率最高为n^(1/2)。

本题中为了方便,采用分层hash的策略,将值为key的元素放入bucke[k/320][k%320]中。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
int table[320][320];
int count[320];
int stack[320*320],top=0;
void push(int e){
stack[top++]=e;
table[e/320][e%320]++;
count[e/320]++;
}
void pop(void){
if(top==0)
printf("Invalid\n");
else{
int e=stack[--top];
printf("%d\n",e);
table[e/320][e%320]--;
count[e/320]--;
}
}
void peekmedian(void)
{
if(top==0)
printf("Invalid\n");
else
{
int k=(top+1)/2,i,c=0;
for(i=0;i<320;++i){
if(c+count[i]>=k)break;
c+=count[i];
}
for(int j=0;j<320;++j){
c+=table[i][j];
if(c>=k){
printf("%d\n",i*320+j);break;
}
}
}
}
int main(){
int n,e;
char s[12];
scanf("%d",&n);
while(n--){
scanf("%s",s);
switch(s[1]){
case 'u':{scanf("%d",&e);push(e);};break;
case 'o':pop();break;
case 'e':peekmedian();break;
}
}
return 0;
}

运行结果:

坚持原创技术分享,您的支持将鼓励我继续创作
-------------本文结束感谢您的阅读-------------
0%