Skip to content

Commit dab7d23

Browse files
author
0x01f7
committed
solve: Find Median from Data Stream
1 parent f2958ee commit dab7d23

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
| # | Title | Solution | Difficulty |
55
|-----|---------------------------------------------------------------------|---------------|-------------|
66
| 296 | [Best Meeting Point][p296] | :lock: | Medium |
7-
| 295 | [Find Median from Data Stream][p295] | | Hard |
7+
| 295 | [Find Median from Data Stream][p295] | [Ruby][s295] | Hard |
88
| 294 | [Flip Game II][p294] | :lock: | Medium |
99
| 293 | [Flip Game][p293] | :lock: | Easy |
1010
| 292 | [Nim Game][p292] | [Ruby][s292] | Easy |
@@ -566,6 +566,7 @@
566566
[p2]:https://leetcode.com/problems/add-two-numbers/
567567
[p1]:https://leetcode.com/problems/two-sum/
568568

569+
[s295]:./algorithms/find_median_from_data_stream.rb
569570
[s292]:./algorithms/nim_game.rb
570571
[s290]:./algorithms/word_pattern.rb
571572
[s283]:./algorithms/move_zeroes.rb
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# https://leetcode.com/problems/find-median-from-data-stream/
2+
#
3+
# Median is the middle value in an ordered integer list. If the size of
4+
# the list is even, there is no middle value. So the median is the mean
5+
# of the two middle value.
6+
#
7+
# Examples:
8+
#
9+
# [2,3,4] , the median is 3
10+
# [2,3], the median is (2 + 3) / 2 = 2.5
11+
#
12+
# Design a data structure that supports the following two operations:
13+
#
14+
# + void addNum(int num) - Add a integer number from the data stream
15+
# to the data structure.
16+
# + double findMedian() - Return the median of all elements so far.
17+
#
18+
# For example:
19+
#
20+
# add(1)
21+
# add(2)
22+
# findMedian() -> 1.5
23+
# add(3)
24+
# findMedian() -> 2
25+
26+
27+
class PriorityQueue
28+
def initialize(cmp)
29+
@queue, @cmp = [], cmp
30+
end
31+
32+
def <<(value)
33+
@queue << value; _swim_(@queue.size - 1); self
34+
end
35+
36+
def shift
37+
@queue[0], @queue[-1] = @queue[-1], @queue[0]
38+
@queue.pop.tap { _sink_(0) }
39+
end
40+
41+
def peek
42+
@queue[0]
43+
end
44+
45+
def size
46+
@queue.size
47+
end
48+
49+
def empty?
50+
@queue.empty?
51+
end
52+
53+
private def _swim_(k)
54+
while k > 0 && @cmp.call(@queue[k], @queue[(k - 1) / 2])
55+
@queue[k], @queue[(k - 1) / 2] = @queue[(k - 1) / 2], @queue[k]
56+
k = (k - 1) / 2
57+
end
58+
end
59+
60+
private def _sink_(k)
61+
while k * 2 + 1 < @queue.size
62+
kk = k * 2 + 1
63+
kk += 1 if @queue[kk + 1] && @cmp.call(@queue[kk + 1], @queue[kk])
64+
break if @cmp.call(@queue[k], @queue[kk])
65+
66+
@queue[k], @queue[kk] = @queue[kk], @queue[k]
67+
k = kk
68+
end
69+
end
70+
end
71+
72+
73+
class MedianFinder
74+
# Initialize your data structure here.
75+
def initialize
76+
@maxpq = PriorityQueue.new(->(x1, x2) { x1 > x2 })
77+
@minpq = PriorityQueue.new(->(x1, x2) { x1 < x2 })
78+
end
79+
80+
# @param {integer} num
81+
# @return {void}
82+
# Adds a num into the data structure.
83+
def add_num(num)
84+
if @maxpq.empty?
85+
@maxpq << num; return
86+
end
87+
88+
if @maxpq.size == @minpq.size
89+
@maxpq << num
90+
else
91+
@minpq << num
92+
end
93+
94+
if @maxpq.peek > @minpq.peek
95+
@maxpq << @minpq.shift
96+
@minpq << @maxpq.shift
97+
end; nil
98+
end
99+
100+
# @return {double}
101+
# Returns median of current data stream
102+
def find_median
103+
@maxpq.size == @minpq.size ? (@maxpq.peek + @minpq.peek).fdiv(2) : @maxpq.peek
104+
end
105+
end
106+
107+
108+
# Your MedianFinder object will be instantiated and called as such:
109+
# mf = MedianFinder.new
110+
# mf.add_num(1)
111+
# mf.find_median()

0 commit comments

Comments
 (0)