[英]Ruby how to return index of a pair
Today I got a task with given array and 'target' which is a sum of 2 integers within that list. 今天,我得到了具有给定数组和“目标”的任务,该任务是该列表中2个整数的总和。 After some time I came out with draft solution but it does not seem to be passing all of the tests.
一段时间后,我提出了解决方案草案,但似乎并没有通过所有测试。 Algorithm seems to be considering integer at [0] twice.
算法似乎在[0]处考虑了两次整数。
def two_sum(numbers, target)
numbers.combination 2 do |a, b|
if a + b == target
return numbers.index(a), numbers.index(b)
end
end
end
print two_sum([1, 2, 3], 4) # Expected [0, 2] *OK
print two_sum([1234, 5678, 9012], 14690) # Expected [1, 2] *OK
print two_sum([2, 2, 3], 4) # Expected [0, 1]) but I get [0, 0]
I have tried to use .map first instead of .combination(2) method but with the exact same result :-/ 我尝试先使用.map而不是.combination(2)方法,但结果完全相同:-/
def two_sum(numbers, target)
[*0..numbers.size-1].combination(2).find { |i,j| numbers[i] + numbers[j] == target }
end
two_sum([1234, 5678, 9012], 14690)
#=> [1, 2]
two_sum([1234, 5678, 9012], 14691)
#=> nil
Here is a more efficient method that may prove useful when the arrays are large. 这是一种更有效的方法,当阵列很大时,可能会有用。
require 'set'
def two_sum(arr, target)
if target.even?
half = target/2
first = arr.index(half)
if first
last = arr.rindex(half)
return [first, last] unless last.nil? || first == last
end
end
a1, a2 = arr.uniq.partition { |n| n <= target/2 }
s = a2.to_set
n = a1.find { |n| s.include?(target-n) }
n.nil? ? nil : [arr.index(n), arr.index(target-n)]
end
If target
is even I first check to see if one-half of it appears at least twice in arr
. 如果
target
是偶数,我首先检查一下它是否有一半至少在arr
出现两次。 If so, we are finished (except for determining and returning the associated indices). 如果是这样,我们就完成了(确定和返回关联的索引除外)。 Even if the method does not terminate after this step it is required this step does not result in an early termination it is required before the next steps are performed.
即使该方法在此步骤之后没有终止,也要求该步骤不会导致在执行后续步骤之前提前终止。
If target
is odd or is even but one-half of it appears less than twice in arr
I construct a temporary array that contains unique values in arr
and then partition that into two arrays, a1
, containing values no greater than target/2
and a2
, containing values greater than target/2
. 如果
target
是奇数或偶数,但一半在arr
出现少于两次,则我构造一个临时数组,在arr
中包含唯一值,然后将其划分为两个数组a1
,其值不大于target/2
和a2
,其值大于target/2
。 It follows that if two numbers sum to target
one must be in a1
and the other must be in a2
. 因此,如果两个数之和
target
必须是a1
,另一个必须在a2
。
To speed calculations I then convert a2
to a set s
, and then loop through a1
looking for a value n
such that s
contains target-n
. 为了加快计算速度,我然后将
a2
转换为集合s
,然后遍历a1
寻找值n
,使s
包含target-n
。 Let's try it. 让我们尝试一下。
arr = 100_000.times.map { rand(1_000_000) }
puts "target i1 arr[i1] i2 arr[i2] calc time (secs)"
puts "---------------------------------------------------------"
1000.times do
t = Time.now
target = rand(1_000_000)
i1, i2 = two_sum(arr, target)
print "#{target} -> "
print i1.nil? ? "nil " :
"#{i1} #{arr[i1]} #{i2} #{arr[i2]}"
puts " #{(Time.now-t).round(4)} secs"
end
prints 版画
target i1 arr[i1] i2 arr[i2] calc time (secs)
---------------------------------------------------------
215113 -> 41 90943 11198 124170 0.027
344479 -> 0 78758 63570 265721 0.0237
188352 -> 190 79209 39912 109143 0.0275
457 -> nil 0.0255
923135 -> 78 84600 43928 838535 0.0207
59391 -> 2 5779 5454 53612 0.0289
259142 -> 73 58864 29278 200278 0.0284
364486 -> 8049 182243 89704 182243 0.001
895164 -> 13 205843 7705 689321 0.0228
880575 -> 20 440073 6195 440502 0.021
We see that arr
does not contain two numbers that sum to 457
. 我们看到
arr
不包含两个总和为457
数字。 Also, notice the very short time in the antepenultimate row. 另外,请注意倒数第二行中的时间很短。 That's because one-helf of
target
( 364486/2 #=> 182243
) appears at least twice in arr
. 那是因为
target
一小部分( 364486/2 #=> 182243
)在arr
出现至少两次。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.