看来你不能跳过 nlogn 所以基本版本只是:
def naive(arr)
res = Array.new(arr.size,0)
for i in 0..arr.length-1
for j in i+1..arr.length-1
res[i] += 1 if arr[i] >= arr[j]
end
end
res
end
但是,根据您的数据集,您可以进行一些优化。例如,在您的示例中存在重复 - 我们可以使用该事实来避免两次遍历相同数字的数组。在这种情况下,而不是搜索小于当前的数字 - 您可以对大于当前的每个数字(从右到左)进行加法并忽略已经使用的数字:
def rightleft(arr)
ignore = {}
res = Array.new(arr.size,0)
(arr.size-1).downto(0) do |i|
current = arr[i]
next if ignore[current]
additor = 1
(i-1).downto(0) do |j|
if arr[i] <= arr[j]
res[j] += additor
if arr[i] == arr[j]
additor += 1
ignore[current] = true
end
end
end
end
res
end
让我们举一些重复的例子:
A = %W{1 2 2 3 3 5 4 6 5 7 8 9 10 11 12 14 5 6 4 3 1 7 8 9 3 5 4 2 2 3 3 5 4 6 5 7 8 9 10 11 12 14 5 6 4 3 1 7 8 9 3 5 4 6 5 7 8 9 10 11 12 14 5 6 4 3 1 10 2 11 12 4 13 1 2 2 3 3 5 4 12 14 5 6 4 3 1 7 8 9 3 5 4 6 5 7 8 9 10 11 12 14 5 6 4 3 1 10 2 11 12 4 13 1 2 2 3 3 5 4 6 5 7 8 9 10 11 12 14 6 5 7 8 9 10 11 12 14 5 6 4 3 1 10 2 11 12 4 13 1 2 2 3 3 5 4 12 14 5 6 4 3 1 7 8 9 3 5 4 6 5 7 8 9 10 11 12 14 5 6 4 3 1 10 2 11 12 4 13 1 2 2 3 3 5 4 6 5 7 8 9 10 11 12 14 5 6 4 3 1 7 8 9 1 10 2 11 12 4 13 14 6 15 12 16 17 18 19}.map(&:to_i)
现在基准测试
puts "NAIVE 100 times:"
puts time_elapsed{
100.times do
naive(A)
end
}
puts "rl 100 times"
puts time_elapsed{
100.times do
rightleft(A)
end
}
结果:
NAIVE 100 times:
[14, 30, 29, 53,...., 0, 0]
Time elapsed 485.935997 milliseconds
rl 100 times
[14, 30, 29, 53,...., 0, 0]
Time elapsed 81.735048 milliseconds
但是当你没有重复时 - 这种优化会使它稍微变慢。以下是数字 1,2,3...,99,100 的结果:
NAIVE 100 times:
[70, 7,... 1, 0]
Time elapsed 99.58762899999999 milliseconds
rl 100 times
[70, 7, ... 1, 0]
Time elapsed 113.186392 milliseconds