我需要查找数组中的两个数字是否等于特定数字。
def sum?(array, num)
end
sum?([1, 2, 3], 5) #=> true
sum?([1, 2, 3], 6) #=> false
是否有使用订单小于N ^ 2的集合的解决方案?另外,有没有办法在不使用集合的情况下获得N ^ 2?
答案 0 :(得分:4)
使用集合,特定数字的查找大致不变。对于数组中的每个数字,只有一个其他数字可以使总和工作。扫描阵列是线性的。
require 'set'
def sum?(array, num)
set = array.to_set
array.any? { |x| set.include?(num - x) }
end
集合转换近似为线性(N个插入),any?
是线性的,因为最坏情况迭代每个元素一次,并且每个元素在集合中具有近似恒定的查找。所以整体线性。
如果num
为偶数且数组包含num/2
的单个副本,则此方法失败。这是另一个线性检查,我将把它留作练习。
答案 1 :(得分:0)
这里天真的策略非常简单:
None
使用def sum?(array, n)
array.reject do |v|
v >= n
end.combination(2).any? do |a, b|
a + b == n
end
end
似乎非常严厉,因为你必须计算所有可能总和的整个集合。对于重复测试,它会更有效,您只需要计算一次设置,但对于单次测试,效率较低。这实际上取决于您的使用案例。
例如:
Set
您可以尝试使用基准测试来查看更长的数字列表的性能。
答案 2 :(得分:0)
您要求提供基于设置的解决方案。如果你想避免导入,你可以使用rubys" Enumerable #uniq"而不是函数(也在Array中实现),它创建一个没有dublicate条目的新数组。下一步是确定数组的最小int值,并从您希望的sum值中减去该值。像这样计算的值是您拥有的最大允许值。然后你可以拒绝其他人。到目前为止,根据ruby文档中的C-Code,所有操作似乎都是O(N)。最后你可以使用Enumerable#any?功能,就像你的pereferd解决方案一样。
这里有一些未经测试的代码:
def sum?(array,num)
rest = array.uniq
max_allowed = num - rest.min
rest.reject! {|value| value > max_allowed}
rest.any? {|value| rest.include?(num - value)}
end
用于计算: array.uniq与转换为集合几乎相同,所以让我们跳过这个。 计算最大允许值为O(1)+ O(N) 拒绝是O(N) 任何?应该导致平均O(N * log(N))
得出结果:O(1)+ 2 * O(N)+ O(N * log(N)) 根据大O符号,这是O(N * log(N)),因为它是最小的部分,小于O(N ^ 2)