Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何降低此功能的复杂性?_Ruby_Algorithm_Time Complexity - Fatal编程技术网

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”中,而不是一个链表中。实际上并没有这样做,因为最坏情况对于正确的哈希函数来说太少了。