解决Kata时需要优化的建议

时间:2016-11-01 17:17:46

标签: ruby optimization runtime

我在代码战中正在做Katas而我偶尔会通过所有测试,但由于超时原因而失败。您能否通过重构下面的代码来帮助评论如何改进我的代码。

arrAarrB是数组,rng是范围,wanted是“奇数”或“偶数”。我需要返回一个数组,该数组包含在每个数组中存在多次的数字,并且在该范围内并且是奇数或偶数。

def find_arr(arrA, arrB, rng, wanted)
  common = arrA && arrB

  range = (rng[0]..rng[1]).to_a.select {|num| common.include?(num)}

  range_wanted = range.select {|num| wanted == "odd" ? num.odd? : num.even?}

  numbers_twice = range_wanted.select {|num| arrA.count(num) > 1 && arrB.count(num) > 1}
end

1 个答案:

答案 0 :(得分:1)

这里存在很多问题,主要是时间复杂度为O(n ^ 2),因为最后一行计算两个数组中的出现次数。对于range_wanted中的每个数字,它需要迭代两个数组的所有元素。这是非常低效的。

尝试使用find_arr([], [], [1, 10_000_000], "odd")或更大范围的参数在irb中运行代码。

以下是如何改进此代码的一些建议:

  1. 通过将它们存储在哈希
  2. 中来计算出现次数
  3. 计算时,您可以跳过那些不符合要求,范围和奇数/偶数
  4. 的数字
  5. 如果要检查值是否在某个范围内,则应使用cover?类中的Range方法。不要将范围更改为数组并迭代它。
  6. 在这一行range_wanted = range.select {|num| wanted == "odd" ? num.odd? : num.even?}中,您在每次迭代中都在测试wanted == "odd",但这不会随着它作为参数传递而发生变化。您可以将此条件移出循环
  7. 这是重构的代码。我把它写在脑后,所以可能会有一些问题,但它应该让你知道如何编写自己的解决方案。

    def find_arr(arrA, arrB, rng, wanted)
      countA = Hash.new(0)
      countB = Hash.new(0)
    
      # If wanted == "odd" we want to test elem % 2 == 1, otherwise elem % 2 == 0
      remainder = wanted == "odd" ? 1 : 0
      range = (rng[0]..rng[1])
    
      arrA.each do |elem|
        if range.cover?(elem) && (elem % 2 == remainder)
          countA[elem] += 1
        end
      end
    
      arrB.each do |elem|
        if range.cover?(elem) && (elem % 2 == remainder)
          countB[elem] += 1
        end
      end
    
      result = []
    
      countA.each do |elem, count|
        if count > 1 && countB[elem] > 1
          result.push(elem)
        end
      end
    
      result
    end