-
Notifications
You must be signed in to change notification settings - Fork 0
/
max-window.rb
141 lines (108 loc) · 2.17 KB
/
max-window.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require 'benchmark'
def windowed_max_range(arr, window) #O(n * w)?
current_max_range = nil
(arr.count - window + 1).times do |idx|
slice = arr[idx..idx + window - 1]
min = slice.min
max = slice.max
range = max-min
current_max_range ||= range
current_max_range = range if range > current_max_range
end
current_max_range
end
def queue_max_range(arr, window)
disp_arr = arr.dup
queue = StackQueue.new
window.times do
queue.enqueue(disp_arr.pop)
end
max_range = queue.max - queue.min
until disp_arr.empty?
queue.enqueue(disp_arr.pop)
queue.dequeue
current_range = (queue.max - queue.min)
max_range = current_range if current_range > max_range
end
max_range
end
class StackElement
attr_reader :val, :min, :max
def initialize(val, min, max)
@val = val
min ||= val
max ||= val
@min = val < min ? val : min
@max = val > max ? val : max
end
end
class MyStack
def initialize
#each store element is { value => [min, max] }
@store = []
end
def pop
return nil if empty?
@store.pop.val
end
def push(el)
@store.push(StackElement.new(el, min, max))
end
def peek
@store.last.val
end
def empty?
@store.empty?
end
def max
return nil if empty?
@store.last.max
end
def min
return nil if empty?
@store.last.min
end
def size
@store.size
end
end
class StackQueue
def initialize
@in_stack = MyStack.new
@out_stack = MyStack.new
end
def enqueue(element)
@in_stack.push(element)
end
def dequeue
return nil if empty?
if @out_stack.empty?
fill_out_stack
end
@out_stack.pop
end
def fill_out_stack
until @in_stack.empty?
@out_stack.push(@in_stack.pop)
end
end
def size
@in_stack.size + @out_stack.size
end
def empty?
size.zero?
end
def min
[@in_stack.min, @out_stack.min].compact.min
end
def max
[@in_stack.max, @out_stack.max].compact.max
end
end
if __FILE__ == $PROGRAM_NAME
array = (1..1_000_000).to_a.shuffle
Benchmark.bmbm do |x|
x.report("dumb: ") { windowed_max_range(array, 5) }
x.report("queue:") { queue_max_range(array, 5) }
end
end