295. Find Median from Data Stream

For example: 1 2 -3 4 => the ans: -3 1 2 4 => Median is 1.5

separate into two heaps (minheap), large and small

ๆฆ‚ๅฟตๆ˜ฏๅˆ†ๆˆๅ…ฉ็พค, ๅฐ็š„็พคๅ–ๆœ€ๅคง็š„, ๅคง็š„็พคๅ–ๆœ€ๅฐ็š„,

็ตฑไธ€้ƒฝ็”จmin heap, ๆ‰€ไปฅๅŠ ๅˆฐ small ๆ™‚, ้ƒฝๆœƒ็”จ่ฒ ็š„ๅŠ ๅ…ฅ,

้€้Ž-large.poll(), ๆŠŠๅฐ็š„ๅŠ ๅˆฐsmall

large.add((long)num);
small.add(-large.poll());

if (large.size() < small.size()) {

็”จไพ†็ถญๆŒๅ…ฉ้‚Š heap ๆ•ธ้‡ๅนณ่กก,

็•ถsmall ๅคชๅคšๆ™‚, ๅˆฉ็”จlarge.add(-small.poll()); ๅŠ ๅ›žๅŽปlarge

=> -small.poll() ๆญคๆ™‚้›–็„ถๆ˜ฏๅ…ถpoll min, ไฝ†ๅ…ถๅฏฆๆœƒๆ˜ฏๆŠŠ"ๆœ€ๅคง"็š„ๅŠ ๅ›ž large (ๅ› ็‚บไน‹ๅ‰้ƒฝๆ˜ฏๆŠŠ่ฒ ้Ž็š„ๅ€ผๅŠ ๅˆฐsmall), ๅ› ็‚บไน‹ๅ‰่ฒ ้Ž, ๆ‰€ไปฅ่ฆๅœจ่ฒ ๅ›žไพ†

็•ถๅฅ‡ๆ•ธๅ€‹ๆ•ธๆ™‚, large ๆœƒๆฏ”่ผƒๅคšๅ€‹ๆ•ธ,

ๅถๆ•ธๅ€‹ๆ•ธๆ™‚, large ๅ’Œsmallใ€€็š„ๅ€‹ๆ•ธๆœƒไธ€ๆจฃ

        if (large.size() < small.size()) {
            large.add(-small.poll());
        }

ๅฅ‡ๆ•ธcase

For example: 1 2 -3

the ans: -3 1 2

when 1 enter, large.add(1)

small: 
large: 1

small.add(-large.poll()) => small.add(-1)

small: -1
large:

=> small size > large size (ๅฅ‡ๆ•ธๆ™‚, ็ถญๆŒ large ๆฏ”่ผƒๅคšๅ€‹ๆ•ธ

=> -small.poll() -(-1) add to large

small: 
large: 1

when 2 enter, large.add(2)

small: 
large: 1, 2

small.add(-large.poll()) => small.add(-1)

small: -1

large: 2

when -3 enter, large.add(-3)

small: -1

large: 2, -3

small.add(-large.poll()) => small.add(3)

small: -1, 3

large: 2

=> small size > large size

=> -small.poll() -(-1) add to large

small: 3 

large: 2, 1 => large ๅ–ๆœ€ๅฐ (min heap peek()

ๅฅ‡ๆ•ธๆ™‚, ๅฐฑๅ–large ็š„ๆœ€ๅฐๅณๅฏ

ๅถๆ•ธcase

For example: 1 2 -3 4

the ans: -3 1 2 4

small: 3, -1 => small ๅ–ๆœ€ๅฐ (min heap peek()

large: 2, 4 => large ๅ–ๆœ€ๅฐ (min heap peek()

ๅถๆ•ธๆ™‚, small large ๅ…ฉ้‚Šๆ•ธ้‡็›ธ็ญ‰,

ไธญไฝๆ•ธ: large ๅ–ๆœ€ๅฐ, small ๅ–ๆœ€ๅฐ(ๅ…ถๅฏฆไปฃ่กจๅฏฆ้š›ไธŠๆœ€ๅคง, ๅ› ็‚บๅŠ ๅ…ฅๆ™‚้ƒฝไฝœ้Ž่ฒ ่™Ÿ),

็›ธๅŠ ้™ค2 โ‡’ 2 -(-1) /2 = 1.5 (ๅ› ็‚บsmall ๆ”พๅ…ฅๆ™‚้ƒฝๆ˜ฏๆ”พ่ฒ ็š„, ๆ‰€ไปฅ่ฆ็”จ - ๅŽปๅŠ )

time: O(logn)

space: O(n)

class MedianFinder {
    
    private PriorityQueue<Long> large;
    private PriorityQueue<Long> small;

    /** initialize your data structure here. */
    public MedianFinder() {
        large = new PriorityQueue<>();
        small = new PriorityQueue<>();
    }
    
    public void addNum(int num) {
        large.add((long)num);
        small.add(-large.poll());
        if (large.size() < small.size()) {
            large.add(-small.poll());
        }
    }
    
    public double findMedian() {
        // notice divide by 2.0, or the presision lost
        return (large.size() > small.size()) ? large.peek() : (large.peek() - small.peek())/2.0;
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

Last updated