如何使用两个for循环优化程序

时间:2018-09-18 18:33:13

标签: ruby-on-rails ruby algorithm

我有一个以下程序

def calc_res(a)
  n = a.length
  result = 0
  for i in 0 .. (n - 1)
    for j in i .. (n - 1)
      if (a[i] != a[j] && j - i > result) then
        result = j - i
      end
    end
  end
  return result
end

返回以下输出

irb(main):013:0> calc_res([4, 6, 2, 2, 6, 6, 4])
=> 5

,但是如果数组大小太大(例如, [0,1,2,3,.....70000]

任何人都可以建议我如何优化它。

谢谢

3 个答案:

答案 0 :(得分:1)

如果我已经理解您要解决的问题(通过代码)

def calc_res(a)
  last_index = a.length - 1
  index = 0
  while a[index] == a.last do
    index = index + 1
    break if index == last_index
  end
  last_index - index
end

它从头开始检查项目是否等于从头开始的项目,结束时它将索引移到最后一个元素。据我了解,您正在搜索不同元素之间的最大长度。

对于您的[4,6,2,2,6,6,4,4]问题,它将有一个迭代并返回5,对于[1 ... 70000]的问题,它将有0迭代并返回这两个位置的差异(数组的大小-1)

答案 1 :(得分:0)

A more rubyesque versions include:

def calc_res(a)
  last = a.last
  idx = a.find_index {|e| e != last }&.+(1) || a.size
  a.size - idx
end

def calc_res(a)
  last = a.last
  a.size - a.each.with_index(1).detect(->{[a.size]}) {|e,_| e != last }.last 
end

def calc_res(a)
  last = a.last
  a.reduce(a.size) do |memo, e| 
    return memo unless e == last
    memo -= 1
  end
end

def calc_res(a)
  return 0 if b = a.uniq and b.size == 1
  a.size - a.index(b[-1]).+(1)
end

答案 2 :(得分:0)

我的理解是,问题在于要在数组中找到两个唯一的元素,它们之间的距离(索引差)最大,并返回它们分开的距离。如果所有元素都相同,我将返回nil

我的解决方案试图在确定最佳解决方案之前将必须检查的成对元素的数量减至最少。对于问题中给出的示例,只需考虑两对元素。

def calc_res(a)
  sz = a.size-1
  sz.downto(2).find { |n| (0..sz-n).any? { |i| a[i] != a[i+n] } }
end

a = [4,6,2,2,6,6,4]
calc_res a
  #=> 5

如果sz = a.size-1sz是两个元素可以分开的最大距离。例如,如果a = [1,2,3,4]sz = 3(位置14分开)

对于asz = a.size-1 #=> 6。我首先确定相隔n = sz个位置的元素对是否唯一。 [a[0], a[6]] #=> [4,4]6彼此分开的唯一一对元素。由于它们不是唯一的,因此我将n减少一个(至5),并检查所有成对的元素n的位置,寻找元素唯一的一个。有两对5位相距的位置:[a[0], a[5]] #=> [4,6][a[1], a[6]] #=> [6,4]。这两个都符合测试,因此我们完成了操作,然后返回n #=> 5。实际上,我们在测试了这两对中的第一对之后就完成了。如果这些对都不包含唯一值n会减少14并且三对[a[0], a[4]] #=> [4,6][a[1], a[5]] #=> [6,6][a[2], a[6]] #=> [2,6]已搜索具有唯一值的一个,依此类推。

请参见Integer#downtoEnumerable#findEnumerable#any?