Ruby Arrays-есть ли элементы, где сумма элементов слева равна сумме элементов справа?
Учитывая массив Ruby, мне нужно найти, существует ли элемент, в котором сумма элементов слева от элемента равна сумме элементов справа от него.
Пример
[1,2,3,3]
Элемент равен 3, потому что сумма элементов слева от 3 [1,2] равна сумме элементов справа от 3.
Я не знаю, как решить эту проблему, но я попробую.
def left_equal_right(array)
array.any? do |x|
index = array.index(x)
array[0..index-1].inject(:+) == array[index+1..-1].inject(:+)
end
end
array.any?([1,2,3,3])
=> returns true, but I'm not sure this method works for larger arrays.
4 ответов:
Это похоже на решение @Max, хотя я могу завершить поиск раньше, когда все элементы в массиве неотрицательны. Это потому, что разница между правой суммой и левой суммой будет монотонно уменьшаться по мере прохождения через массив.
Мой ответ предполагает, что должен быть по крайней мере один элемент на каждой стороне, но он, конечно, может быть изменен, чтобы разрешить ноль элементов на одной стороне.Код
def balance(arr) return nil if arr.size < 3 all_non_neg = (arr.min >= 0) enum = arr.to_enum last = enum.next diff = arr.reduce(:+)-last (1..arr.size-2).each do |i| val = enum.next diff += -last - val return i if diff.zero? return -i if all_non_neg && diff < 0 last = val end nil endЗдесь, когда поиск завершается рано, я возвращаю отрицательный индекс, где это происходит. Это только для иллюстрации;
nilбыло бы более уместно.Примеры
balance [1,1,1,1,1] #=> 2 balance [-1,-1,-1] #=> 1 balance [3,4,-6,7,5,-6,4,3,5,2] #=> 4 balance [3,4,-6,7,5,-6,4,3,5,2,4,7] #=> nil balance [3,7,2,28,6,5,8,7] #=> 1 balance [3,7,2,28,6,5,8,7] #=> -4Как указано, в последнем примере поиск был завершен по индексу 4.
Это должно быть быстрее всего, так как он не суммирует весь массив каждую итерацию:
def left_equal_right ary left = 0 right = ary.reduce(:+) ary.each do |x| right -= x return true if left == right left += x end false endНа моей виртуальной машине это проверяет массив из 10 миллионов элементов за 2 секунды.
Работает для массивов длиной 10 000 (всего несколько секунд)
Тайм-аут для массивов длиной 100 000
left_equal_right (1..100_000).to_a # =Execution timed out.Однако, если вы измените свой код следующим образом:
def left_equal_right(array) array.any? do |x| index = array.index(x) left_sum = 0 right_sum = 0 left_index = 0 right_index = 0 while left_index < index left_sum += array[left_index] left_index += 1 end while right_index < array.count right_sum += array[right_index] right_index += 1 end return left_sum == right_sum end endТогда вы можете обрабатывать гораздо большие массивы, я пробовал до 10 миллионов:
left_equal_right (1..10_000_000).to_a # ==> false
Попробуйте это-лучший способ получить индексы:
array.each_index.any? do |i| array[0..i-1].inject(:+) == array[i+1..-1].inject(:+) endЭто все еще делает много ненужно повторяющейся работы, но он получает работу и избегает проблемы, которую ваше решение вводит с помощью
Array#index.
Comments