LeetCode 295 – 数据流的中位数

题目描述

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
例如 arr = [2,3,4] 的中位数是 3 。
例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类:
MedianFinder() 初始化 MedianFinder 对象。
void addNum(int num) 将数据流中的整数 num 添加到数据结构中。
double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

题目分析

使用两个优先队列,一个大顶存储左侧数据,一个小顶存储右侧数据。
插入数据时,根据大小决定插入左侧还是右侧。然后再对两个队列元素的数量做平衡(差距超过2)。
插入数据的时间复杂度是 O(log n),读取中位数的时间复杂度是 O(1)

Java

private Queue<Integer> left = new PriorityQueue<>((o1, o2) -> Integer.compare(o2, o1));
private Queue<Integer> right = new PriorityQueue<>();

public MedianFinder() {

}

public void addNum(int num) {
    if (right.isEmpty()) {
        right.offer(num);
        return;
    }
    if (num > right.peek()) {
        right.offer(num);
        if (right.size() > left.size() + 1) {
            left.offer(right.poll());
        }
    } else {
        left.offer(num);
        if (left.size() > right.size() + 1) {
            right.offer(left.poll());
        }
    }
}

public double findMedian() {
    if (left.size() > right.size()) {
        return (double) left.peek();
    } else if (left.size() < right.size()) {
        return (double) right.peek();
    } else {
        return (left.peek() + right.peek()) / 2.0;
    }
}

Kotlin

private val left = PriorityQueue<Int> { o1, o2 -> Integer.compare(o2, o1) }
private val right = PriorityQueue<Int>()

fun addNum(num: Int) {
    if (left.isEmpty()) {
        left.offer(num)
        return
    }
    if (num < left.peek()) {
        left.offer(num)
        if (left.size > right.size + 1) {
            right.offer(left.poll())
        }
    } else {
        right.offer(num)
        if (right.size > left.size + 1) {
            left.offer(right.poll())
        }
    }
}

fun findMedian(): Double {
    if (left.size > right.size) {
        return left.peek().toDouble()
    } else if (left.size < right.size) {
        return right.peek().toDouble()
    } else {
        return (left.peek() + right.peek()) / 2.0
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部