你有一个整数数组,并且对于每个索引,你想要找到除了该索引处的整数之外的每个整数的乘积

时间:2016-09-06 01:13:25

标签: arrays ruby big-o complexity-theory greedy

我正在浏览一些面试问题并在一个网站上遇到过这个问题。我已经提出了Ruby的解决方案,我想知道它是否有效并且是一个可接受的解决方案。我现在已经编写了一段时间,但从未专注于解决方案的复杂性。现在我正在努力学习最小化时间和空间的复杂性。

问题: 你有一个整数数组,并且对于每个索引,你想要找到除了该索引处的整数之外的每个整数的乘积。

示例:

arr = [1,2,4,5]
result = [40, 20, 10, 8]

# result = [2*4*5, 1*4*5, 1*2*5, 1*2*4]

考虑到这一点,我提出了这个解决方案。

解决方案:

def find_products(input_array)
    product_array = []
    input_array.length.times do |iteration|
        a = input_array.shift
        product_array << input_array.inject(:*)
        input_array << a
    end
    product_array
end

arr = find_products([1,7,98,4])

根据我的理解,我访问数组的次数与其长度一样多,这在效率和速度方面被认为是可怕的。我仍然不确定我的解决方案的复杂程度。

任何有助于提高效率的帮助都是值得赞赏的,如果您还能说出我的解决方案的复杂性以及如何计算,那就更好了。

由于

4 个答案:

答案 0 :(得分:3)

def product_of_others(arr)
  case arr.count(0)
  when 0
    total = arr.reduce(1,:*)
    arr.map { |n| total/n }
  when 1
    ndx_of_0 = arr.index(0)
    arr.map.with_index do |n,i|
      if i==ndx_of_0
        arr[0,ndx_of_0].reduce(1,:*) * arr[ndx_of_0+1..-1].reduce(1,:*)
      else
        0
      end
    end
  else
    arr.map { 0 }
  end
end

product_of_others [1,2,4,5]  #=> [40, 20, 10, 8]
product_of_others [1,-2,0,5] #=> [0, 0, -10, 0]
product_of_others [0,-2,4,5] #=> [-40, 0, 0, 0] 
product_of_others [1,-2,4,0] #=> [0, 0, 0, -8]
product_of_others [1,0,4,0]  #=> [0, 0, 0, 0]
product_of_others []         #=> []

对于arr不包含零的情况,我使用arr.reduce(1,:*)而不是arr.reduce(:*),以防数组为空。同样,如果arr包含一个零,我使用.reduce(1,:*)以防零位于数组的开头或结尾。

答案 1 :(得分:2)

对于不包含零的输入(对于其他输入,请参见下文)

对我来说最简单(而且相对有效)似乎首先得到了总产品:

total_product = array.inject(1){|product, number| product * number}

然后将每个数组元素映射到total_product除以元素:

result = array.map {|number| total_product / number}

初步计算total_product = 1*2*4*5后,这将计算

result = [40/1, 40/2, 40/4, 40/5]

据我记得,这总计为O(n)[创建总产品:触摸每个数字一次] + O(n)[每个数字创建一个结果:触摸每个数字一次]。 (如果我错了,纠正我

<强>更新

正如@hirolau和@CarySwoveland指出的那样,如果输入中有(正好为1)0,则存在问题:

对于包含零的输入(解决方法,但借用性能优势和复杂性类)

zero_count = array.count{|number| number == 0}
if zero_count == 0
  # as before
elsif zero_count == 1
  # one zero in input, result will only have 1 non-zero
  nonzero_array = array.reject{|n| n == 0}
  total_product = nonzero_array.inject(1){|product, number| product * number}
  result = array.map do |number|
    (number == 0) ? total_product : 0
  end
else
  # more than one zero? All products will be zero!
  result = array.map{|_| 0}
end

很抱歉,现在这个答案基本上等于@CarySwoveland,但我认为我的代码更明确。 请查看有关进一步性能考虑的评论。

答案 2 :(得分:0)

我将如何做到这一点:

arr = [1,2,4,5]

result = arr.map do |x|
  new_array = arr.dup  # Create a copy of original array
  new_array.delete_at(arr.index(x)) # Remove an instance of the current value
  new_array.inject(:*) # Return the product.
end

p result  # => [40, 20, 10, 8]

答案 3 :(得分:-2)

我不知道ruby,但是,访问数组是O(1),这意味着它处于恒定时间,因此算法的复杂性为O(n),非常好。我不认为在复杂性方面可以找到更好的解决方案。真正的速度是另一个问题,但这个解决方案很好