问题描述:
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
算法:
- 用list存储,每次add,直接用append进行。O(1)
在findMedian中,直接进行list.sort(),返回中间值。
在findMedian的算法中,时间复杂度为O(n*logn)。
整个算法复杂度为O(k + t*nlogn)=O(n*logn)结果超时。k为调用add次数,t为调用findMedian次数。 - 在add的时候进行二叉搜索,确定插入位置,使用list.insert()进行插入。一次add的时间复杂度为O(logn + n)。
在findMedian中,直接返回中间值。O(1)
这个算法的复杂度为O(k *logn +k* n+t)=O(n)结果Accepted。k为调用add次数,t为调用findMedian次数。 - 还有更快的算法吗?
答案是,还有。。。
分析题目所求结果,其与有序数组的中间两个元素相关,可惜这两个元素在数组中间。。。是的,在中间!有没有办法把数组劈开使中间的两个元素暴露出来,并且这两个元素分别是左半个数组的最大值,是右半个数组的最小值。对,这正是大小堆结构。
这样,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