剑指OFFER_数据流中的中位数

剑指OFFER_数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

思路

我觉得刷题的思路应该是从无到有,然后再从有到更好;

秉持着这样的思路,先从最简单的思路解这道题,按照题意先做一个容器容纳这个数据流;

然后对这个容器排序,并记录容器长度;

输出结果时,如果长度为奇数,则输出中位数,为偶数则求均值;

优化的思路就是就是sort函数,倒不是说sort函数不好用,而是其实vector中其实本来就排好顺序的,只是增加一个,所以只需要插入一个数到这个有序的容器中就好了,很自然的就想到了二分法;

好吧其实完成后也没提高多少,从5ms提升到了3ms,代码如下:

代码_暴力

class Solution {
public:
    int len = 0;
    vector<int> S;
    void Insert(int num)
    {
        ++len;
        S.push_back(num);
        
        // 待优化
        sort(S.begin(), S.end());
    }

    double GetMedian()
    { 
        if (len % 2 == 1) {
            return (double)S[len/2];
        }else {
            return (double)(S[len/2]+S[len/2-1])/2;
        }
    }

};

代码_二分法

class Solution {
public:
    int len = 0;
    vector<int> S;
    
    void dichotomy(int begin, int end, const int& num) {
        if (end - begin <= 1) {
            if (num < S[begin]) {
                S.insert(S.begin()+begin, num);
            }else if (num > S[end]) {
                S.insert(S.begin()+end+1, num);
            }else{
                S.insert(S.begin()+end, num);
            }
            return;
        }
    	int mid = (begin + end)/2;
    	if (S[mid] > num) {
    		dichotomy(begin, mid, num);
    	} else {
    		dichotomy(mid, end, num);
    	}
    }
    void Insert(int num)
    {
        if (len == 0) {
        	S.push_back(num);
        }else {
        	dichotomy(0, len-1, num);
        }
     	++len;  
    }

    double GetMedian()
    { 
        if (len % 2 == 1) {
            return (double)S[len/2];
        }else {
            return (double)(S[len/2]+S[len/2-1])/2;
        }
    }

};
原文地址:https://www.cnblogs.com/sakurapiggy/p/13194917.html