leetcode295/剑指offer41.数据流的中位数

1.题目描述

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3) 
findMedian() -> 2
进阶:

如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

2.解题思路

进阶一:数据流中所有整数都在 0 到 100 范围内

用一个数组保存每个数字出现的次数。

时间复杂度和空间复杂度均是O(1)。

JAVA代码:

public class MedianFinder {
 
    int[] count;
    int total;
 
    /** initialize your data structure here. */
    public MedianFinder() {
        count = new int[101];
        total = 0;
    }
 
    public void addNum(int num) {
        count[num]++;
        total++;
    }
 
    public double findMedian() {
        if (0 == total % 2) {
            return (findKthNumber(total / 2) + findKthNumber(total / 2 + 1)) / 2.0;
        } else {
            return findKthNumber(total / 2 + 1);
        }
    }
 
    private int findKthNumber(int k) {
        int index = 0;
        for (int i = 0; i < 101; i++) {
            index += count[i];
            if (index >= k) {
                return i;
            }
        }
        return -1;
    }
 
}

进阶二:数据流中 99% 的整数都在 0 到 100 范围内


和进阶一同样的思路,只不过将大于100的数除去即可,因为有99%的整数都在0到100范围内,所以中位数一定是0到100范围内的某个数,只需根据大于100的数的个数在进阶一的基础上调整即可。

时间复杂度和空间复杂度均是O(1)。
 

public class MedianFinder {
 
    int[] count;
    int total;
    int greaterThan100;
 
    /** initialize your data structure here. */
    public MedianFinder() {
        count = new int[101];
        total = 0;
        greaterThan100 = 0;
    }
 
    public void addNum(int num) {
        if (num <= 100) {
            count[num]++;
        } else {
            greaterThan100++;
        }
        total++;
    }
 
    public double findMedian() {
        int temp = total - greaterThan100 * 2;
        if (0 == temp % 2) {
            return (findKthNumber(greaterThan100 + temp / 2) + findKthNumber(greaterThan100 + temp / 2 + 1)) / 2.0;
        } else {
            return findKthNumber(greaterThan100 + temp / 2 + 1);
        }
    }
 
    private int findKthNumber(int k) {
        int index = 0;
        for (int i = 0; i < 101; i++) {
            index += count[i];
            if (index >= k) {
                return i;
            }
        }
        return -1;
    }
 
}

参考:https://blog.csdn.net/qq_41231926/article/details/90576809#comments

3.代码实现

class MedianFinder(object):

    def __init__(self):
        """
        initialize your data structure here.
        """

        self.maxheap=[]
        self.minheap=[]
        

    def addNum(self, num):
        """
        :type num: int
        :rtype: None
        """
        # 数字来了就往大根堆里插入
        heapq.heappush(self.maxheap,-num)
        # 如果逆序就交换
        if len(self.minheap)>0 and self.minheap[0] < -self.maxheap[0]:
            t1=heapq.heappop(self.minheap)
            t2=-heapq.heappop(self.maxheap)
            heapq.heappush(self.minheap,t2)
            #把小的取出来,重新放入大根堆,还是要取负
            heapq.heappush(self.maxheap,-t1)
        # 如果下多就转移
        if len(self.maxheap)-len(self.minheap)>1:
            t2=-heapq.heappop(self.maxheap)
            heapq.heappush(self.minheap,t2)
        

    def findMedian(self):
        """
        :rtype: float
        """
        if (len(self.maxheap)+len(self.minheap))%2==0:
            return (self.minheap[0]+(-self.maxheap[0]))/2.0
        else:
            return -self.maxheap[0]
        


# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值