我在代码战中正在做Katas而我偶尔会通过所有测试,但由于超时原因而失败。您能否通过重构下面的代码来帮助评论如何改进我的代码。
arrA
和arrB
是数组,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
答案 0 :(得分:1)
这里存在很多问题,主要是时间复杂度为O(n ^ 2),因为最后一行计算两个数组中的出现次数。对于range_wanted
中的每个数字,它需要迭代两个数组的所有元素。这是非常低效的。
尝试使用find_arr([], [], [1, 10_000_000], "odd")
或更大范围的参数在irb中运行代码。
以下是如何改进此代码的一些建议:
cover?
类中的Range
方法。不要将范围更改为数组并迭代它。range_wanted = range.select {|num| wanted == "odd" ? num.odd? : num.even?}
中,您在每次迭代中都在测试wanted == "odd"
,但这不会随着它作为参数传递而发生变化。您可以将此条件移出循环这是重构的代码。我把它写在脑后,所以可能会有一些问题,但它应该让你知道如何编写自己的解决方案。
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