Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<= 105). Then N lines follow, each contains a command in one of the following 3 formats:
Push keyPop
PeekMedian
where key is a positive integer no more than 105.
Output Specification:
For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print "Invalid" instead.
Sample Input:17 Pop PeekMedian Push 3 PeekMedian Push 2 PeekMedian Push 1 PeekMedian Pop Pop Push 5 Push 4 PeekMedian Pop Pop Pop PopSample Output:
Invalid Invalid 3 2 2 1 2 4 4 5 3 Invalid
思路:
题目除了正常的进栈和出栈操作外增加了获取中位数的操作, 获取中位数,我们有以下方法:
(1):每次全部退栈,进行排序,太浪费时间,不可取。
(2):题目告诉我们key不会超过10^5,我们可以想到用数组来标记,但不支持快速的统计操作。
因为同一个数可能出现多次。想到用一个array来记录长度,但是还是O(N)超时,后来上网查询,要用树状数组!
(3):然后将数组转为树状数组,可以快速的统计,再配上二分就OK了。
AC参考代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
const int Max_required = 100005;
int tree_array[Max_required];
inline int lowbit(int x)
{
return x&(-x);
}
void add(int x, int value) //更新前n项和函数
{
while (x < Max_required)
{
tree_array[x] += value;
x += lowbit(x);
}
}
int sum(int x) //求前n项和函数
{
int total = 0;
while (x > 0)
{
total += tree_array[x];
x -= lowbit(x);
}
return total;
}
int binary_find(int x) //二分查找代码
{
int low = 1, high = Max_required, mid;
while (low <= high)
{
mid = (low + high) >> 1;
int total = sum(mid);
if (total >= x)
high = mid - 1;
else if (total < x)
low = mid + 1;
}
return low;
}
int main()
{
int n;
stack<int> st;
while (scanf("%d", &n) != EOF)
{
memset(tree_array, 0, sizeof(tree_array));
char ch[30];
while (n--)
{
scanf("%s", ch);
if (strcmp("Push", ch) == 0)
{
int pp;
scanf("%d", &pp);
st.push(pp);
add(pp, 1);
}
else if (strcmp("Pop", ch) == 0)
{
if (st.empty())
printf("Invalid\n");
else
{
printf("%d\n", st.top());
add(st.top(), -1);
st.pop();
}
}
else if (strcmp("PeekMedian", ch) == 0)
{
int len = st.size();
if (len == 0) {
printf("Invalid\n");
continue;
}
int res = -1;
if (len % 2 == 1)
res = binary_find((len + 1) / 2);
else
res = binary_find(len / 2);
printf("%d\n", res);
}
}
}
return 0;
}
树状数组简单介绍:
假设数组a[1..n],那么查询a[1]+...+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。
来观察这个图:
int lowbit(int x){
return x&(-x);
}
本文介绍如何实现一种特殊的数据结构——栈,该栈除了支持常规的压栈和弹栈操作外,还能高效地返回当前所有元素的中位数。通过使用树状数组,实现了快速统计和查找中位数的功能。
5571

被折叠的 条评论
为什么被折叠?



