名企面試:Aamazon筆試題(Find median in a stream )

Aamazon筆試題(Find median in a stream )

題意:
Given an input stream of n integers the task is to insert integers to stream and print the median of the new stream formed by each insertion of x to the stream.
給你一個輸入流,會往這個流中插入整數,你的任務是每次插入一個整數之後計算當前的中位數是多少。
Example
流的數據 : 5, 15, 1, 3
5 進入流 –> 中位數 5 (5)
15 進入流 –> 中位數 10 (5, 15)
1 進入流 –> 中位數 5 (5, 15, 1)
3 進入流 –> 中位數 4 (5, 15, 1, 3)
輸入描述:
第一行是n的大小,接着輸入n個數。
輸出描述:
每一測試輸出n個數,表示插入第i個數之後的中位數。
Constraints:
1<=N<=10^5+7
1<=x<=10^5+7
Example:
Example:
Input:
4
5
15
1
3
Output:
5
10
5
4
分析:
筆試和麪試題都有一個很大的規律,就是一定可以直接想到最暴力的方法,所以在面試的時候,不要着急,先給出暴力方法,在思考更好的方法,不要直接就去想最優的方法。對於這個題,每次插入數字之後,我們可以之間快速排序取中間即可其時間複雜度是O(n*n*logn),還可以用插入排序,因爲每一個的數據都是有序的,插入排序會更好,如果在定位的時候用到二分又會進一步提高性能。之後纔是怎樣更進一步的解決這個問題呢?中位數?就是中間的數,保證左邊的所有數字小於或者等於這個數,右邊的所有數字大於或者等於這個數,而且,左右兩邊的數字的個數相差不超過1。
如果我們每一次插入一個新的數時,都維護兩個部分,使得左邊的部分小於或等於這個數,右邊的部分大於或等於這個數,並保證左右兩邊的數字的個數相差不超過1。此時的中位數就之後三種情況:
1、左邊的個數>右邊的個數: 取出左邊最大的一個數就是中位數
2、左邊的個數<右邊的個數: 取出右邊最小的一個數就是中位數
3、左邊的個數=右邊的個數: (取出左邊最大的一個數就是中位數 + 取出右邊最小的一個數就是中位數)/ 2,就是中位數。
每次我們都要取出左邊最大值或者右邊的最小值,因此我們想到一個數據結構堆,左邊申請一個大根堆,右邊申請一個小根堆。維護這兩個堆即可。
時間複雜度是O(nlogn)。空間複雜度是O(n)。

Code:

/**
 *Author: xiaoran
 *座右銘:既來之,則安之
 */
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
typedef long long LL;
const int MAXN = 1005;

int main() {
    //code
    int n,x;
    while(cin>>n){
        vector<int> a;
        priority_queue <int> minheap;//count left part 值越大優先級越大
        priority_queue <int,vector<int>,greater<int> > maxheap;// right part值越小優先級越大
        int minsize,maxsize,current_med;
        minsize = maxsize = current_med = 0;
        for(int i=0;i<n;i++){
           cin>>x;
           a.push_back(x);
           //如果當前的值大於中位數,就插入到右邊的小根堆
           if(x <= current_med){
               minheap.push(x);
               minsize ++;
           }
           else{
               maxheap.push(x);
               maxsize ++;
           }
           //有一邊超過了兩個數,證明二者必須分開
           if(maxsize - minsize >= 2){
               int tmp = maxheap.top();
               maxheap.pop();
               maxsize --;
               minheap.push(tmp);
               minsize ++;
           }
           if(minsize - maxsize >= 2){
               int tmp = minheap.top();
               minheap.pop();
               minsize --;
               maxheap.push(tmp);
               maxsize ++;

           }
           //cout<<"minsize:"<<minsize<<endl;
           //cout<<"maxsize:"<<maxsize<<endl;

           //根據三種情況得到中位數
           if(maxsize == minsize){
               current_med = (maxheap.top() + minheap.top()) / 2;
           }
           if(maxsize < minsize){
               current_med = minheap.top();
           }
           if(maxsize > minsize){
               current_med = maxheap.top();
           }
            cout<<current_med<<endl;           
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章