我会让其他人调试您的代码。相反,我想提出另一种可以相对有效地进行计算的方法。
def two_sum(nums, target)
h = nums.each_with_index.with_object(Hash.new { |h,k| h[k] = [] }) do |(n,i),h|
h[n] << i
end
n,i = nums.each_with_index.find { |n,_i| h.key?(target-n) }
return nil if n.nil?
indices = h[target-n]
return [i,indices.first] unless n == target/2
return nil if indices.size == 1
[i, indices.find { |j| j !=i }]
end
two_sum([2,7,11,15], 9) #=> [0, 1]
two_sum([2,7,11,15], 10) #=> nil
two_sum([2,7,11,15], 4) #=> nil
two_sum([2,7,11,2,15], 4) #=> [0, 3]
two_sum([2,11,7,11,2,15,11], 22) #=> [1, 3]
在最后一个例子中
h #=> {2=>[0, 4], 11=>[1, 3, 6], 7=>[2], 15=>[5]}
请注意,哈希中的键查找非常快,特别是行的执行
indices = h[target-n]
构建h 的计算复杂度为 O(n),其中n = num.size 和余数非常接近 O(n)(“非常接近”,因为键查找接近于恒定时间),整体计算复杂度接近 O(n),而考虑num 中每对值的蛮力方法是 O(n^2)。
如果定义了哈希
h = Hash.new { |h,k| h[k] = [] }
当h 没有键k 时执行h[k] 导致
h[k] = []
被执行。例如,如果
h #=> { 2=>[0] }
然后
h[11] << 1
原因
h[11] = []
被执行(因为h没有密钥11),之后
h[11] << 1
被执行,导致
h #=> { 2=>[0], 11=>[1] }
相比之下,如果那时
h[2] << 3
执行我们得到
h #=> { 2=>[0,3], 11=>[1] }
没有 h[2] = [] 被执行,因为 h 已经有一个密钥 2。见Hash::new。
将块变量表示为
|(n,i),h|
是array decomposition 的一种形式。