zoukankan      html  css  js  c++  java
  • lintcode-81-数据流中位数

    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)

    标签

    优先队列 LintCode 版权所有 堆 谷歌

    思路

    参考http://www.cnblogs.com/easonliu/p/4441916.html

    • 使用一个最大堆 maxSet 与最小堆 minSet( maxSet 用 multiset 的反向遍历代替)。maxSet 存的是到目前为止较小的那一半数,minSet 存的是到目前为止较大的那一半数,这样中位数只有可能是 maxSet 的堆顶元素(本题中)或者是两个堆顶元素的均值。
    • minSet与maxSet交替使用,保证两个堆的大小之差不超过1。
    • 当插入一个新数时,若新数大于 minSet 的堆顶元素,说明新数在所有数的下半部分,此时将新数插入 minSet,取出 minSet 堆顶元素并插入至 maxSet ;否则,说明新数在所有数的上半部分,将新数插入 maxSet
    • 当插入一个新数时,若新数小于 maxSet 的堆顶元素,说明新数在所有数的上半部分,此时将新数插入 maxSet,取出 maxSet 堆顶元素并插入至 minSet ;否则,说明新数在所有数的下半部分,将新数插入 minSet
    • 将 maxSet 堆顶元素存入返回值数组,但不取出堆顶元素

    code

    class Solution {
    public:
        /**
         * @param nums: A list of integers.
         * @return: The median of numbers
         */
        vector<int> medianII(vector<int> &nums) {
            // write your code here
            int size = nums.size();
            if (size <= 0) {
                return vector<int>();
            }
            // maxSet存的是到目前为止较小的那一半数,minSet存的是到目前为止较大的那一半数
            // maxSet使用反向遍历,达到最大堆效果
            multiset<int> minSet, maxSet;
            vector<int> result;
            bool flag = true;
            for (int i = 0; i < size; i++) {
                int temp = nums[i];
                // minSet与maxSet交替使用,保证两个堆的大小之差不超过1
                if (flag) {
                    // 新数大于minSet的堆顶元素时,说明新数在所有数的下半部分
                    if (!minSet.empty() && nums[i] > *minSet.begin()) {
                        minSet.insert(nums[i]);
                        temp = *minSet.begin();
                        minSet.erase(minSet.find(temp));
                    }
                    // 新数小于minSet的堆顶元素时,说明新数在所有数的上半部分
                    // 或将原minSet的堆顶元素放在maxSet中
                    maxSet.insert(temp);
                }
                else {
                    // 新数小于minSet的堆顶元素时,说明新数在所有数的上半部分
                    if (!maxSet.empty() && nums[i] < *maxSet.rbegin()) {
                        maxSet.insert(nums[i]);
                        temp = *maxSet.rbegin();
                        maxSet.erase(maxSet.find(temp));
                    }
                    // 新数大于minSet的堆顶元素时,说明新数在所有数的下半部分
                    // 或将原maxSet的堆顶元素放在minSet中
                    minSet.insert(temp);
                }
                flag = !flag;
                result.push_back(*maxSet.rbegin());
            }
            return result;
        }
    };
    
  • 相关阅读:
    Python基础之迭代器、生成器
    Python基础之模块+异常
    Python基础之面向对象思维解决游戏《天龙八部》
    Oracle创建存储过程
    数据库范式
    Oracle条件判断
    Oracle的三种循环
    Oracle的pl/sql变量类型
    oracle如何实现去重和分页
    相关子查询和非相关子查询
  • 原文地址:https://www.cnblogs.com/libaoquan/p/7380890.html
Copyright © 2011-2022 走看看