Median in Q41 data stream

Median in the data stream

topic

How to get the median in a data stream? If an odd number of values ​​is read from the data stream, the median is the value in the middle after all values ​​are sorted. If an even number of values ​​is read from the data stream, then the median is the average of the middle two numbers after all values ​​are sorted. We use the Insert () method to read the data stream, and the GetMedian () method to get the median of the currently read data.

Ideas

If you can get all the data, you can use the quick partition function to find the number taken at the kth position. Complexity is O ( n ) O (n)

But in the case of data flow, every time you add one, and line up once, it becomes O ( n 2 ) O (n ^ 2) ?

I hope that after each additional number, you can quickly find the current median.

You can use two sets to achieve. One stores the number to the left of the median, and one stores the number to the right of the median.

median
/multiset for left numbers\
/multiset for right numbers\

The default is to use the multiset less<T>comparison function, * begin () is the minimum value acquired obtained.

Thus, two set defined as follows, using the std::greater<>functor.

std::multiset<int, std::less<int>> rightNums; //存储右边的数字,头部为右边最小的数字
std::multiset<int, std::greater<int>> leftNums; //存储左边的数字,头部为左边最大的数字
  1. When adding a new number, the current even number will default to the left, the current odd number will default to the right.
  2. When putting it on the left, check if num is greater than the minimum value on the right,
    1. If it is greater, move the minimum value on the right to the left and put the new num on the right.
    2. If not greater, just put it on the left
  3. Put it on the right, similar.

When obtaining the median, determine the number of digits in the current two sets:

  • When odd, the median is the top of the left set. (Even numbers are placed on the left by default, and the total number is odd after they are placed).
  • For even numbers, the total number of digits is the average of the top of left and right.

achieve

class Solution {
public:
    void Insert(int num)
    {
        int size = rightNums.size() + leftNums.size();
        if(!(size & 0x1))//偶数
        {
            if(rightNums.size()!=0 && num > (*rightNums.begin()) )
            {
                int minInRight = *rightNums.begin();
                rightNums.erase(rightNums.begin());
                rightNums.insert(num);
                leftNums.insert(minInRight);
            }
            else
                leftNums.insert(num);
        }
        else
        {//奇数
            if(leftNums.size()!=0 && num < (*leftNums.begin()) )
            {
                int maxInLeft = *leftNums.begin();
                leftNums.erase(leftNums.begin());
                leftNums.insert(num);
                rightNums.insert(maxInLeft);
            }
            else
                rightNums.insert(num);
        }
    }

    double GetMedian()
    { 
        int size = rightNums.size() + leftNums.size();
        if(!(size & 0x1))
        {//偶数
            return ((*leftNums.begin())+(*rightNums.begin()))/2.0;
        }
        else
        {//奇数,放在left里面
            return (*leftNums.begin());
        }
    }

private:
    std::multiset<int, std::less<int>> rightNums;
    std::multiset<int, std::greater<int>> leftNums;
};
发布了58 篇原创文章 · 获赞 11 · 访问量 3万+

Guess you like

Origin blog.csdn.net/mhywoniu/article/details/105606299