Ruby 如何降低此功能的复杂性?
我得到了这个函数:Ruby 如何降低此功能的复杂性?,ruby,algorithm,time-complexity,Ruby,Algorithm,Time Complexity,我得到了这个函数: 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,
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))?我对ruby不太熟悉,但在我看来,您似乎在试图找出有多少个连续的子数组和sum
您的代码执行了一个蛮力的操作:查找所有子数组-O(N^2)
,将它们相加,然后检查它们是否匹配。
这总计为O(N^3)code 这可以更有效地完成1: 定义一个新数组
sums
,如下所示:
sums[i] = arr[0] + arr[1] + ... + arr[i]
在O(N)
时间内计算上述值很容易。请注意,假设为非负数-此和
数组已排序
现在,迭代sums
数组,并对每个元素sums[i]
进行二进制搜索,如果存在一些索引j
,使得sums[j]-sums[i]==SUM
。如果答案为真,则加1(如果数组可以包含零,则需要进行更简单的工作,这不会影响复杂性)
由于搜索是二进制搜索,每次迭代都是在O(logN)
中进行的,并且对每个元素都进行搜索,因此实际上有O(NlogN)
算法
类似地,将sums
中的元素添加到散列集中,而不是将它们放在排序数组中,您可以达到O(N)
平均案例性能,因为现在查找每个元素的平均值是O(1)
伪代码:
input: arr , sum
output: numOccurances - number of contiguous subarrays that sums to sum
currSum = 0
S = new hash set (multiset actually)
for each element x in arr:
currSum += x
add x to S
numOccurances= 0
for each element x in S:
let k = number of occurances of sum-x in the hashset
numOccurances += k
return numOccurances
请注意,哈希集变量不需要非负数的限制,也可以处理它
(1) 假设您的数组只包含非负数。您应该更详细地说明您在这里要实现的目标。无论如何,计算具有特定和的子阵列的数量可以这样做:
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
顺便说一句,你的例子应该返回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
根据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
def get_sum_切片3(a,sum)
s=a.inject([]){| m,e | m这个算法试图实现什么,它在高层次上做了什么?也许你可以更明确地解释一下你想用这个函数实现什么。这是我在计算机科学研究中的一项任务。我需要将这个函数的复杂度降低到O(N*log(N))或者更好。这是一个匹配子数组和问题吗?为什么它返回“2”?这是第一个切片的大小吗?非常感谢您的快速回答。然而,切片只使用了一对整数,但我不太清楚如何将其集成到您的函数中。但仍然是相同的复杂性?@Cojones不,这是O(N^2),与O(N^3)相反,您的代码实现了O(N)优化,而O(N)优化的复杂性明显更低,因为没有注入-cycle@Cojones请注意,这绝对不是O(nlogn)。有一个嵌套循环重复n*n次,这是O(n^2)代码,它确实比您的代码好,但比O(n)或O(nlogn)慢得多。但这是下一个问题。谢谢你的详细回答!我如何在你的伪代码中得到sum的出现次数?它是sum-x的出现次数(不是sum
),它是多集实现的一部分。实现它的简单方法是使用映射/字典,在第一个循环中-当添加到S
时,如果x
已经在S
中,则添加1+S[x]
(如果不是,则设置S[x]=1
),然后检索它只是S[x]
的值。(记住S
是一本字典)希望我很清楚。Hashset有O(1)个平均情况。最坏情况下的性能是什么?@hyades通常O(n)
,但可以将其改进为O(logn)
,方法是将其放在每个“bin”中,而不是一个链表中。实际上并没有这样做,因为最坏情况对于正确的哈希函数来说太少了。