Leetcode
  • Leetcode Questions
  • Runtime Screenshots
  • DataStructure
    • Leetcode 394. Decode String
    • Leetcode 225. Implement Stack Using Queues
    • Leetcode 336. Palindrome Pairs
    • Leetcode 316. Remove Duplicate Letters
    • Leetcode 206. Reverse Linked List
    • Leetcode 347. Top K Frequent Elements
    • Leetcode 227. Basic Calculator II
    • Leetcode 224. Basic Calculator
  • Linear
    • Leetcode 23. Merge k Sorted Lists
    • Leetcode 48. Rotate Image
    • Leetcode 6. ZigZag Conversion
    • Leetcode 438. Find All Anagrams in a String
    • Leetcode 189. Rotate Array
    • LeetCode 56. Merge Intervals
    • Leetcode 4. Median of Two Sorted Array
    • Leetcode 3. Longest Substring Without Repeating Characters
    • Leetcode 8. String to Integer (atoi)
    • Leetcode 5. Longest Palindromic Substring
    • Leetcode 11. Container With Most Water
  • Tree
    • Leetcode 103. Binary Tree Zigzag Level Order Traversal
    • Leetcode 508. Most Frequent Subtree Sum
    • Leetcode 226. Invert Binary Tree
    • Leetcode 222. Count Complete Tree Nodes
    • Leetcode 250. Count Univalue Subtrees
    • Leetcode 285. Inorder Successor in BST
    • Leetcode 230. Kth Smallest Element in a BST
    • Leetcode 543. Diameter of Binary Tree
    • Leetcode 199. Binary Tree Right Side View
  • Math
    • Leetcode 50. Power(x, n)
    • Leetcode 166. Fraction to Recurring Decimal
    • Leetcode 7. Reverse Integer
    • Leetcode 360. Sort Transformed Array
    • Leetcode 367. Valid Perfect Square
    • Leetcode 12. Integer to Roman
  • DynamicProgramming
    • Leetcode 10. Regular Expression Matching
    • Leetcode 253. Meeting Rooms II
    • Leetcode 303. Range Sum Query
    • Leetcode 22. Generate Parentheses
  • Graph
    • Leetcode 142. Linked List Cycle II
    • Leetcode 261. Graph Valid Tree
    • Leetcode 339. Nested List Weight Sum
    • Leetcode 207. Course Schedule
  • OODesign
    • Leetcode 295. Find Media From Data Stream
Powered by GitBook
On this page
  • 题目
  • 思路
  • 解答
  • Complexity Analysis
  • 拓展
  • 总结
  • Reference

Was this helpful?

  1. OODesign

Leetcode 295. Find Media 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.

For example, [2,3,4], the median is 3. [2,3], the median is (2 + 3) / 2 = 3.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.

Example:

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

思路

这道题目最简单粗暴的解法为对所有数进行排序,返回中点。这样时间复杂度非常高,达到惊人的O(nlog(n)). 在此基础上我们可以进行优化,既然要排序,那我们可以使用Insertion Sort的思想,即在插入数时将它 放到排序好的位置。这样时间复杂度就被减少到了O(n)。

我们从以上的两种初级方法中发现,这道题目提升速度的核心在于:通过某种方式保持存储元素的顺序,以此 Constant Time返回相应中点。为了在此基础上进一步提升,我们首先回忆中点的定义。

中点将数组分为Larger和Smaller两个满足以下条件的部分:
  - 两个部分大小相等
  - Larger中的所有元素比Smaller中所有元素大

以此我们可以发现,找中点并不需要保持所有元素的顺序!我们只要保证所有元素能被分为两个数量相等的部分, 且Larger中的最小数 > Smaller中的最大数即可。在这个条件下,中点就是这两个最大最小数中的一个或者 它们的平均值。

最大最小这两个关键词提示我们可以使用Heap(Java中的PriorityQueue)来实现这个算法。我们要保证两个 条件: 1. 两个Heap大小相等 2. 装较小元素们的Heap的最大值 (maxHeap) < 装较大元素们的Heap的最小值 (minHeap)

解答

class MedianFinder {

    PriorityQueue<Integer> minHeap; // keeps the larger part of elements
    PriorityQueue<Integer> maxHeap; // keeps the smaller part of elements

    /** initialize your data structure here. */
    public MedianFinder() {
        minHeap = new PriorityQueue<Integer>();
        maxHeap = new PriorityQueue<Integer>(Collections.reverseOrder());
    }

    public void addNum(int num) {
        minHeap.offer(num);
        // smallest of the larger part > biggest of the smaller part
        if (!minHeap.isEmpty() && !maxHeap.isEmpty() && minHeap.peek() < maxHeap.peek()) { 
            Integer temp = minHeap.poll();
            minHeap.offer(maxHeap.poll());
            maxHeap.offer(temp);
        }
         // make sure they are equal in length
        if (minHeap.size() > maxHeap.size()) {
            maxHeap.offer(minHeap.poll());
        }
    }

    public double findMedian() {
        if ((minHeap.size() + maxHeap.size()) % 2 == 0) {
            return (minHeap.peek() + maxHeap.peek()) / 2.0;
        }
        return maxHeap.peek();
    }
}
/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

Complexity Analysis

  • Time Complexity:

    • addNum(int n)时间复杂度为O(log(n)),每次插入最多有四次Heap offer()即为O(4 * log(n)).

    • findMedian()时间复杂度为O(1). 每次查询只需O(1)的时间拿出两个Heap的最大最小。

  • Space Complexity: O(n). 我们需要两个额外的Heap来储存这些元素,即为O(n).

拓展

  • If all integer numbers from the stream are between 0 and 100, how would you optimize it?

  • If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?

  • 除了用Heap之外,我们还可以使用其他的数据结构比如AVL树来实现这个算法吗?

  • 在Leetcode论坛上有讨论多种其他方法,比如Buckets, Reservoir Sampling等等,同学么可以去Reference Link中看看。

总结

一如既往,最难的还是透过问题看本质。类似那道经典的Median of Two Sorted List,我们要深刻理解中点的定义, 并以此启发性地灵活运用数据结构来解决问题。

Reference

PreviousOODesign

Last updated 5 years ago

Was this helpful?

: 多种方法的全面总结

Leetcode Official Solution