[leetcode295]Find Median from Data Stream

问题描述:

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

Examples:
[2,3,4] , the median is 3

[2,3], the median is (2 + 3) / 2 = 2.5

Design a data structure that supports the following two operations:

void addNum(int num) - Add a integer number from the data stream to the data structure.
double findMedian() - Return the median of all elements so far.
For example:

add(1)
add(2)
findMedian() -> 1.5
add(3)
findMedian() -> 2

算法:

  1. 用list存储,每次add,直接用append进行。O(1)
    在findMedian中,直接进行list.sort(),返回中间值。
    在findMedian的算法中,时间复杂度为O(n*logn)。
    整个算法复杂度为O(k + t*nlogn)=O(n*logn)结果超时。k为调用add次数,t为调用findMedian次数。
  2. 在add的时候进行二叉搜索,确定插入位置,使用list.insert()进行插入。一次add的时间复杂度为O(logn + n)。
    在findMedian中,直接返回中间值。O(1)
    这个算法的复杂度为O(k *logn +k* n+t)=O(n)结果Accepted。k为调用add次数,t为调用findMedian次数。
  3. 还有更快的算法吗?
    答案是,还有。。。
    分析题目所求结果,其与有序数组的中间两个元素相关,可惜这两个元素在数组中间。。。是的,在中间!有没有办法把数组劈开使中间的两个元素暴露出来,并且这两个元素分别是左半个数组的最大值,是右半个数组的最小值。对,这正是大小堆结构。
    这样,add函数的时间复杂度为O(logn),findMedian的时间复杂度为O(1).整个算法的时间复杂度为O(logn)。
class MedianFinder:
    """
     Time Limit Exceeded 
    """
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.data = []

    def addNum(self, num):
        """
        Adds a num into the data structure.
        :type num: int
        :rtype: void
        """
        self.data.append(num)

    def findMedian(self):
        """
        Returns the median of current data stream
        :rtype: float
        """
        length = len(self.data)
        self.data.sort()
        if length % 2 == 0:
            return (self.data[length//2] + self.data[length//2-1])*0.5
        else:
            return self.data[length//2]*1.0


import bisect

class MedianFinder:
    """
    Accepted
    """
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.data = []

    def addNum(self, num):
        """
        Adds a num into the data structure.
        :type num: int
        :rtype: void
        """
        bisect.insort(self.data, num)

    def findMedian(self):
        """
        Returns the median of current data stream
        :rtype: float
        """
        length = len(self.data)
        if length % 2 == 0:
            return (self.data[length//2] + self.data[length//2-1])*0.5
        else:
            return self.data[length//2]*1.0


import heapq

class MedianFinder:
    """
     heap implement
    """
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.left = []
        self.right = []

    def addNum(self, num):
        """
        Adds a num into the data structure.
        :type num: int
        :rtype: void
        """
        if len(self.left) == len(self.right):
            heapq.heappush(self.left, -heapq.heappushpop(self.right, num))
        else:
            heapq.heappush(self.right, -heapq.heappushpop(self.left, -num))


    def findMedian(self):
        """
        Returns the median of current data stream
        :rtype: float
        """
        length = len(self.left) + len(self.right)
        if length%2 == 0:
            left = -self.left[0]
            right = self.right[0]
            return 0.5*(left+right)
        else:
            return -self.left[0]*1.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值