2016-12-10 49 views
2

對不起,如果標題不清楚。我遇到了一個解決的問題,但我希望能夠深入瞭解如何在不使用嵌套循環的情況下解決問題,或者如果有更高效的方法。謝謝!更有效的方法來解決Ruby演習要求返回2個索引,而不使用嵌套循環?

# Write a method that takes an array of numbers. If a pair of numbers 
 
# in the array sums to zero, return the positions of those two numbers. 
 
# If no pair of numbers sums to zero, return `nil`. 
 

 
def two_sum(nums) 
 
    nums.each_with_index do |num, i1| 
 
    for i2 in i1 + 1...nums.length 
 
     return [i1, i2] if num + nums[i2] == 0 
 
    end 
 
    end 
 

 
    nil 
 
end 
 

 
# These are tests to check that your code is working. After writing 
 
# your solution, they should all print true. 
 

 
puts(
 
    'two_sum([1, 3, 5, -3]) == [1, 3]: ' + (two_sum([1, 3, 5, -3]) == [1, 3]).to_s 
 
) 
 
puts(
 
    'two_sum([1, 3, 5]) == nil: ' + two_sum([1, 3, 5]).nil?.to_s 
 
)

+0

[比較Ruby中的兩個項目](http://stackoverflow.com/questions/33905245/comparing-two-items-in-array-with-ruby) – tebayoso

+2

編號這只是一個比較的元素。這需要返回他們的指數。 –

+1

更高效的,你的意思是比'O(n^2)'更好的時間複雜度,還是隻是看起來更清晰的代碼?兩者都是有效的追求,但最有可能不會看起來一樣。 –

回答

4

你可以做到以下幾點。

def two_sum(nums) 
    nums.each_with_index.with_object({}) do |(n, idx),h| 
    return [h[-n], idx] if h.key?(-n) 
    h[n] = idx 
    end 
    nil 
end 

two_sum [1,2,4,5,-2,6] 
    #=> [1, 4] 
two_sum [1,2,4,5,-3,6] 
    #=> nil 
two_sum [1,-2,5,-2,6,2] 
    #=> [3, 5] 

如果我改變h[n] = idxh[n] = idx unless h.key?(n)最後上面的例子將返回[1, 5]

對於Enumerable#each_with_object讀者不熟悉的,上面的代碼等同於以下

def two_sum(nums) 
    h = {} 
    nums.each_with_index do |n, idx| 
    return [h[-n], idx] if h.key?(-n) 
    h[n] = idx 
    end 
    nil 
end 
+0

不錯的變化。 –

2

你可以使用這個答案基地開始: https://stackoverflow.com/a/33905895/2552259

然後適應回答您的要求:

def get_two_indexes(ary) 
    aryx = Hash[(0...ary.size).zip ary] 
    couples = aryx.to_a.combination(2).to_a 
    matches = couples.map {|pair| pair.map{|x| x[1]}.inject(:+).zero?} 
    indexes = matches.map.with_index {|match,index| 
    match ? couples[index].map{|x| x[0]} : nil 
    }.compact 
    indexes.empty? ? nil : indexes 
end 

irb > [[1,-1], [0,0], [1,-1,1,-1],[1,2]].map{|ary| get_two_indexes(ary)} 
=> [[[0, 1]], [[0, 1]], [[0, 1], [0, 3], [1, 2], [2, 3]], nil] 

這將返回匹配零和n的匹配組合索引如果沒有值匹配則返回il,如果數組中有重複值,則返回適當的索引。

+0

定義ary,現在返回一組匹配的索引。 – tebayoso

+2

當數組包含兩個零並且沒有其他和爲零的對時存在問題:'index'將返回兩次第一個零的索引。考慮使用'rindex'來找到對的第二個元素的索引, –

+0

我忽略了數組中重複的值,'[0,0]'或'[-1,1,-1,1]'將檢索第一次發生的指數。此外,該問題還指出了其他一些條件,例如:最終返回true,如果沒有匹配,則返回nil。現在改進我的答案。 – tebayoso