简体   繁体   English

Ruby如何返回一对索引

[英]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/2a2 ,其值大于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM