zoukankan      html  css  js  c++  java
  • PAT 1057. Stack

    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 key
    Pop
    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
    Pop
    

    Sample Output:

    Invalid
    Invalid
    3
    2
    2
    1
    2
    4
    4
    5
    3
    Invalid
    

    分析

    这道题蛮有意思的,首先呢,我是直接用vector来实现所有操作,每次peekmedian之前进行排序,结果可想而知,除了第一个测试点和最后一个测试全挂。
    然后度娘了一下,好多大神用什么树状数组,去查阅了一些资料,大致对这个数据结构了解了,这就是下面的解法一,其实呢,说通俗点,用这个数组寻找中位数,就是通过树状数组对求数组任意段子数组和的以及删改和增添元素的便利性来求出任何一个数前面比它小的数有多少个来确定该数是否中位数。
    当然对于像我这种对树状数组一无所知的小白来说呢,理解树状数组还是有那么一丢丢难度的,所以解法二,则很好的可以帮助大家解决这个问题,解法二的分析这里就直接引用别人的了:
    利用set(默认由小到大排序),在Push的时候进行判断然后分别压入s1,s2(s2大于mid,s1小于等于mid);
    
    然后Pop和Push操作的时候分被调整s1,s2以及mid的值。保证s1的大小等于s2的大小或者等于s2的大小+1,这样,s1中的最后一个值就是mid;
    
    注意删除的时候要删除的对象是指针,否则将会把所有值相同的元素都删去
    

    解法一如下

    #include <cstdio>
    #include <stack>
    #define lowbit(i) ((i) & (-i))
    const int maxn = 100010;
    using namespace std;
    int c[maxn];
    stack<int> s;
    void update(int x, int v) {
        for(int i = x; i < maxn; i += lowbit(i))
            c[i] += v;
    }
    int getsum(int x) {
        int sum = 0;
        for(int i = x; i >= 1; i -= lowbit(i))
            sum += c[i];
        return sum;
    }
    void PeekMedian() {
        int left = 1, right = maxn, mid, k = (s.size() + 1) / 2;
        while(left < right) {
            mid = (left + right) / 2;
            if(getsum(mid) >= k)
                right = mid;
            else
                left = mid + 1;
        }
        printf("%d
    ", left);
    }
    int main() {
        int n, temp;
        scanf("%d", &n);
        char str[15];
        for(int i = 0; i < n; i++) {
            scanf("%s", str);
            if(str[1] == 'u') {
                scanf("%d", &temp);
                s.push(temp);
                update(temp, 1);
            } else if(str[1] == 'o') {
                if(!s.empty()) {
                    update(s.top(), -1);
                    printf("%d
    ", s.top());
                    s.pop();
                } else {
                    printf("Invalid
    ");
                }
            } else {
                if(!s.empty())
                    PeekMedian();
                else
                    printf("Invalid
    ");
            }
        }
        return 0;
    }
    

    解法二如下

    #include<iostream>
    #include<stack>
    #define lowbit(i) ((i)&(-i))
    using namespace std;
    const int maxn=100005;
    int c[maxn];
    stack<int> st;
    void update(int x,int v){
    	for(int i=x;i<maxn;i+=lowbit(i))
    	    c[i]+=v;
    }
    int getsum(int x){
    	int sum=0;
    	for(int i=x;i>=1;i-=lowbit(i))
    	    sum+=c[i];
    	return sum;
    }
    void PeekMedian(){
    	int left=1,right=maxn,mid,k=(st.size()+1)/2;
    	while(left<right){
    		mid=(left+right)/2;
    		if(getsum(mid)>=k)
    		   right=mid;
    		else
    		   left=mid+1;
    	}
    	printf("%d
    ",left);
    }
    int main(){
    	int n,num,temp;
    	cin>>n;
    	char order[15];
    	for(int i=0;i<n;i++){
    		scanf("%s",order);
    		if(order[1]=='u'){
    		   scanf("%d",&num);
    		   st.push(num);
    		   update(num,1);
    		}else if(order[1]=='e'){
    			if(st.size()==0)
    			   printf("Invalid
    ");
    			else
    			   PeekMedian();
    		}else if(order[1]=='o'){
    			if(st.size()==0)
    			   printf("Invalid
    ");
    			else{
    				 temp=st.top();
    				 printf("%d
    ",temp);
    				 st.pop();
    				 update(temp,-1);
    			}
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    Java-- 异常之使用finally进行清理
    请几天假
    Java-- 重新抛出异常
    Java-- 异常与记录日志
    Java-- 异常(2)
    Java基础——多线程(4)
    Java基础——多线程(3)
    Java基础——面向对象练习题
    Java基础——多线程(2)
    Java基础——多线程(1)
  • 原文地址:https://www.cnblogs.com/A-Little-Nut/p/8341873.html
Copyright © 2011-2022 走看看