我有这个功能:
def get_sum_slices(a, sum)
count = 0
a.length.times do |n|
a.length.times do |m|
next if n > m
count += 1 if a[n..m].inject(:+) == sum
end
end
count
end
将此[-2, 0, 3, 2, -7, 4]
数组和2
作为和,它将返回2,因为切片的两个总和等于0 - [2]
和[3, 2, -7, 4]
。有人知道如何将其提高到O(N * log(N))?
答案 0 :(得分:4)
我对ruby并不熟悉,但在我看来,你正试图找出总共sum
总共有多少个连续的子数组。
你的代码正在蛮力发现所有子阵列 - O(N^2)
,并将它们相加 - 每个O(N),并检查它是否匹配。
这总计为O(N^3)
代码。
可以更有效地完成 1 :
定义一个新数组sums
,如下所示:
sums[i] = arr[0] + arr[1] + ... + arr[i]
在O(N)
时间内计算上述内容很容易。请注意,假设为非负数 - 此sums
数组已排序。
现在,迭代sums
数组,并对每个元素sums[i]
执行二分搜索,如果有一些索引j
使sums[j]-sums[i] == SUM
。如果答案是真的,加一个(如果数组可以包含零,则需要更简单的工作,它不会影响复杂性。)
由于搜索是二进制搜索,并且每次迭代都在O(logN)
完成,并且您为每个元素执行此操作 - 实际上您拥有O(NlogN)
算法。
同样地,但是将sums
中的元素添加到哈希集中而不是将它们放在排序数组中,您可以达到O(N)
平均大小写性能,因为现在寻找每个元素{{1平均而言。
伪代码:
O(1)
请注意,哈希集变体不需要限制非负数,也可以处理它。
(1)假设你的数组只包含非负数。
答案 1 :(得分:1)
根据amit的算法:
def get_sum_slices3(a, sum)
s = a.inject([]) { |m, e| m << e + m.last.to_i }
s.sort!
s.count { |x| s.bsearch { |y| x - y == sum } }
end
Ruby使用的quicksort在大多数情况下是nlogn
答案 2 :(得分:0)
您应该更好地详述您在此尝试实现的目标。无论如何,计算具有特定总和的子阵列的数量可以这样做:
def get_sum_slices(a, sum)
count = 0
(2..a.length).each do |n|
a.combination(n).each do |combination|
if combination.inject(:+) == sum
count += 1
puts combination.inspect
end
end
end
count
end
btw你的例子应该返回6
irb> get_sum_slices [-2, 0, 3, 2, -7, 4], 0
[-2, 2]
[-2, 0, 2]
[3, -7, 4]
[0, 3, -7, 4]
[-2, 3, 2, -7, 4]
[-2, 0, 3, 2, -7, 4]
=> 6