81.數據流中位數

數字是不斷進入數組的,在每次添加一個新的數進入數組的同時返回當前新數組的中位數。

  • 中位數是排序後數組的中間值,如果有數組中有n個數,則中位數爲A[(n-1)/2]。
  • 比如:數組A=[1,2,3]的中位數是2,數組A=[1,19]的中位數是1。

樣例

持續進入數組的數的列表爲:[1, 2, 3, 4, 5],則返回[1, 1, 2, 2, 3]

持續進入數組的數的列表爲:[4, 5, 1, 3, 2, 6, 0],則返回 [4, 4, 4, 3, 3, 3, 3]

持續進入數組的數的列表爲:[2, 20, 100],則返回[2, 2, 20]

挑戰 

時間複雜度爲O(nlogn)


第一次用的插入排序,花了948ms。

後來改進爲兩個堆,一個最大堆儲存前一半數,一個最小堆儲存後一半數,插入次數是奇數時將值插入最大堆,是偶數時插入最小堆,同時保證最大堆的最大值小於最小堆的最小值。用時59ms。確實快了不少。順便寫了寫堆的插入刪除操作(堆下標從0開始)。

#include<iostream>
#include<vector>
using namespace std;

	void insertmaxheap(vector<int> &maxheap, int tar)
    {
        int pos = maxheap.size();
        maxheap.push_back(tar);
        if(pos == 0)
            return; 
        
        int child = pos;
        int par = (pos-1)/2;
        while(tar > maxheap[par] )
        {
            maxheap[child] = maxheap[par];
            child = par;
            if(par == 0)
                break;
            else
                par = (par-1)/2;
        }
        maxheap[child] = tar;
    }
    int deletemaxheap(vector<int> &maxheap)
    {
        int ret = maxheap[0];
        int pos = maxheap.size()-1;//新的size
        int tar = maxheap[pos];
        maxheap.pop_back();
        
        if(pos == 0)
            return ret;
        else if(pos == 1)
        {
            maxheap[0] = tar;
            return ret;
        }
        else if(pos == 2)
        {
            if(tar>maxheap[1])
            {
                maxheap[0] = tar;
            }
            else
            {
                maxheap[0] = maxheap[1];
                maxheap[1] = tar;
            }
            return ret;
        }
        
        int par = 0;
        int child = maxheap[1] < maxheap[2] ? 2 : 1;
        while(tar < maxheap[child])
        {
            maxheap[par] = maxheap[child];
            par = child;
            if(2*child+1 < pos && 2*child+2>=pos)
                child = 2*child+1;
            else if(2*child+1 >= pos && 2*child+2>=pos)
                break;
            else
                child = maxheap[2*child+1] < maxheap[2*child+2] ? 2*child+2 : 2*child+1;
        }
        maxheap[par] = tar;
        
        return ret;
    }
    void insertminheap(vector<int> &minheap, int tar)
    {
        int pos = minheap.size();
        minheap.push_back(tar);
        if(pos == 0)
            return;

        int child = pos;
        int par = (pos-1)/2;
        while(tar < minheap[par] )
        {
            minheap[child] = minheap[par];
            child = par;
            if(par == 0)
                break;
            else
                par = (par-1)/2;
        }
        minheap[child] = tar;
    }
    int deleteminheap(vector<int> &minheap)
    {
        int ret = minheap[0];
        int pos = minheap.size()-1;//新的size
        int tar = minheap[pos];
        minheap.pop_back();
        
        if(pos == 0)
            return ret;
        else if(pos == 1)
        {
            minheap[0] = tar;
            return ret;
        }
        else if(pos == 2)
        {
            if(tar < minheap[1])
            {
                minheap[0] = tar;
            }
            else
            {
                minheap[0] = minheap[1];
                minheap[1] = tar;
            }
            return ret;
        }
        
        int par = 0;
        int child = minheap[1] > minheap[2] ? 2 : 1;
        while(tar > minheap[child])
        {
            minheap[par] = minheap[child];
            par = child;
            if(2*child+1 < pos && 2*child+2>=pos)
                child = 2*child+1;
            else if(2*child+1 >= pos && 2*child+2>=pos)
                break;
            else
                child = minheap[2*child+1] > minheap[2*child+2] ? 2*child+2 : 2*child+1;
        }
        minheap[par] = tar;
        
        return ret;
    }

	vector<int> medianII(vector<int> &nums) 
	{
        // write your code here
        int m = nums.size();
        if(m==0) return vector<int>(0);
        /*
        vector<int> vec(m, nums[0]);
        //948ms
        int i=0, j=0;
        for(i=1; i<m; i++)
        {
            int temp = nums[i];
            for(j=i; j>0 && temp<nums[j-1]; j--)
            {
                nums[j] = nums[j-1];
            }
            nums[j] = temp;
            vec[i] = nums[i/2];
        }
        return vec;
        */
        vector<int> maxheap;
        vector<int> minheap;
        vector<int> ret(m, 0);
        for(int i=0; i<m; i++)
        {
            
            if(!(i&1))//ji ci
            {
                insertminheap(minheap, nums[i]);
                int min = deleteminheap(minheap);
                insertmaxheap(maxheap, min);
            }
            else// ou ci
            {
                insertmaxheap(maxheap, nums[i]);
                int max = deletemaxheap(maxheap);
                insertminheap(minheap, max);
            }
            ret[i] = maxheap[0];
        }
        return ret;
    }
    

int main()
{
	vector<int> vec = {1,2,3,4,5};
	vector<int> ret(medianII(vec));
	for(auto x:ret)
		cout<<x<<" ";
	cout<<endl;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章