By the way, answering your question...
And how do I get what I want, the two smallest elements (in linear time)?
If this method did not exist or meanwhile it is broken, you can select the two smallest elements in linear time using Quickselect, which is basically what Ruby does in min
under the hood.
Here is my direct translation from Wikipedia:
class Array
def mymin(n)
return self.sort if self.size <= n
a = self.dup
left = 0
right = a.size - 1
loop do
pivot_index = left + (right - left) / 2;
pivot_value = a[pivot_index]
a[pivot_index], a[right] = a[right], a[pivot_index]
store_index = left
left.upto(right - 1).each do |i|
if a[i] < pivot_value
a[store_index], a[i] = a[i], a[store_index]
store_index += 1
end
end
a[right], a[store_index] = a[store_index], a[right]
if n - 1 == store_index
break
elsif n - 1 < store_index
right = store_index - 1
else
left = store_index + 1
end
end
a.take(n).sort
end
end
And then we try your example:
[20, 32, 32, 21, 30, 25, 29, 13, 14].mymin(2)
# => [13, 14]
Yay! We just fixed the min
. Beware though, that this implementation has space complexity linear to the size of the original array, while the Ruby implementation is linear to the value n
. Also, if your original array has too many duplicates, this will have a bad performance and you should look for
3-way partitioning.
If you only want the min
for n = 2 and are really worried about the performance, it is possible to make an optimized version for that case with O(L)
guaranteed (assuming L
is the length of the array).
class Array
def min2
m1 = nil
m2 = nil
self.each do |x|
if m1.nil? || x < m1
m2 = m1
m1 = x
elsif m2.nil? || x < m2
m2 = x
end
end
[m1, m2].compact
end
end
And use it in analogous way:
[20, 32, 32, 21, 30, 25, 29, 13, 14].min2
# => [13, 14]
min_by(2){|i| i}
also returns the wrong result. – Christogram[third, x,x,x,x,x, first, second]
and return[first,third]
– Microampere[13, 20]
. – Alodimax
:[0,0,0,0,0,0,1,3,2].max(2) #=> [3, 1]
– Keheley4
github.com/ruby/ruby/blob/v2_2_3/enum.c#L1272 causes the algorithm to skip the last number when populatingdata
– Herb