您有一个整数数组,对于每个索引,您想要找到除该索引处的整数之外的每个整数的乘积
You have an array of integers, and for each index you want to find the product of every integer except the integer at that index
我正在研究一些面试问题,并在一个网站上看到了这个问题。我在 Ruby 中提出了一个解决方案,我想知道它是否有效且可以接受。我已经编码一段时间了,但以前从未关注过解决方案的复杂性。现在我正在努力学习如何最大限度地减少时间和 space 复杂性。
问题:
您有一个整数数组,对于每个索引,您想要找到除该索引处的整数之外的每个整数的乘积。
示例:
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])
据我了解,我访问数组的次数与其长度一样多,这在效率和速度方面被认为是糟糕的。我仍然不确定我的解决方案有多复杂。
感谢任何有助于提高效率的帮助,如果您还可以告诉我解决方案的复杂性以及如何计算它,那就更好了。
谢谢
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,:*)
以防零位于数组的开头或结尾。
我不知道ruby,但是,访问一个数组是O(1),也就是说是常数时间,所以你的算法复杂度是O(n),很好。我不认为在复杂性方面可以找到更好的解决方案。实际速度是另一个问题,但这个解决方案很好
对于不包含零的输入(对于其他,见下文)
对我来说最简单(也相对有效)的似乎是首先得到总积:
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,就会出现问题,因此:
对于包含零的输入(解决方法,但借用了性能优势和复杂性 class)
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,但我认为我的代码更明确。
查看有关进一步性能考虑的评论。
我会这样做:
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]
我正在研究一些面试问题,并在一个网站上看到了这个问题。我在 Ruby 中提出了一个解决方案,我想知道它是否有效且可以接受。我已经编码一段时间了,但以前从未关注过解决方案的复杂性。现在我正在努力学习如何最大限度地减少时间和 space 复杂性。
问题: 您有一个整数数组,对于每个索引,您想要找到除该索引处的整数之外的每个整数的乘积。
示例:
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])
据我了解,我访问数组的次数与其长度一样多,这在效率和速度方面被认为是糟糕的。我仍然不确定我的解决方案有多复杂。
感谢任何有助于提高效率的帮助,如果您还可以告诉我解决方案的复杂性以及如何计算它,那就更好了。
谢谢
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,:*)
以防零位于数组的开头或结尾。
我不知道ruby,但是,访问一个数组是O(1),也就是说是常数时间,所以你的算法复杂度是O(n),很好。我不认为在复杂性方面可以找到更好的解决方案。实际速度是另一个问题,但这个解决方案很好
对于不包含零的输入(对于其他,见下文)
对我来说最简单(也相对有效)的似乎是首先得到总积:
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,就会出现问题,因此:
对于包含零的输入(解决方法,但借用了性能优势和复杂性 class)
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,但我认为我的代码更明确。 查看有关进一步性能考虑的评论。
我会这样做:
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]