Nano Hash - криптовалюты, майнинг, программирование

Написание функции, которая сравнивает два дерева и возвращает true, если они равны по структуре и значению, и false в противном случае.

Учитывая два дерева, я хочу вернуть true, если они равны по структуре и значению, и false в противном случае.

Учитывая следующий класс:

class TreeNode
  attr_accessor :val, :left, :right

  def initialize val, left = nil, right = nil
    @val = val
    @left = left
    @right = right
  end
end

завершить функцию

def binary_tree_compare(a, b)

Мои исследования привели меня к здесь. Я пробовал рубиновое решение, но безрезультатно. Ниже приведен код, который я пробовал до сих пор:

def binary_tree_compare a, b
  for_check << [a, b]   

  while a,b = for_check.shift  
    return false unless a.children.count == b.children.count 
    break if a.children.empty?

    a_children = a.children.sort 
    b_children = b.children.sort     
    return false unless a_children == b_children  

    0.upto(a_children.count - 1) do |i|
      for_check << [a_children[i], b_children[i]]  
    end
  end
  return true
end

Я ожидаю, что вывод будет истинным, если TreeNodes a и b равны по структуре и значению, и ложным в противном случае.

Я получаю синтаксическую ошибку, и это трассировка стека:

  solution.rb:4: syntax error, unexpected ',', expecting keyword_do_cond or ';' or '\n'
    while a,b = for_check.shift  
           ^
  solution.rb:12: syntax error, unexpected keyword_do_cond, expecting keyword_end
  ...0.upto(a_children.count - 1) do |i|
  ...                             ^~
  olution.rb:15: syntax error, unexpected keyword_end, expecting end-of-input
    end
    ^~~ ```
12.04.2019

  • Пожалуйста, определите дерево как объект Ruby, как вы сделали для узлов дерева. 12.04.2019
  • @CarySwoveland, как именно мне это сделать? 12.04.2019
  • Я понимаю. Деревья определяются их верхними узлами, a и b. 12.04.2019
  • Решение @CarySwoveland @ggorlen ниже, которое я принял, поскольку ответ сработал, поскольку он учитывает узлы a и b. 12.04.2019

Ответы:


1

Во-первых, давайте исправим синтаксические/логические ошибки:

  1. Используйте круглые скобки для обеспечения приоритета оператора:

    while a,b = for_check.shift
    

    должно быть

    while (a, b = for_check.shift)
    
  2. Массив for_check не существует, когда вы пытаетесь поместить в него элемент.

    for_check << [a, b]   
    

    должно быть

    for_check = [a, b]   
    

Во-вторых, ваш код, кажется, не имеет большого отношения к представленной проблеме (хотя одновременный поиск с использованием обоих узлов в стеке — правильная идея). Во-первых, показанный здесь класс TreeNode не имеет массива элементов children. Целью этого кода является обработка общих деревьев с n дочерними элементами, а также игнорирование порядка этих дочерних элементов, две характеристики, которые не являются частью проблемы, с которой вы столкнулись.

Я рекомендую повторно подойти к проблеме, предполагая, что бинарное дерево и порядок дочерних элементов имеют значение, а также их значения.

Если вы хотите спойлер, попробуйте следующую рекурсивную логику (итеративная тоже работает, как вы делаете с явным стеком, и рекомендуется писать обе):

  1. Если один из корней равен нулю, убедитесь, что другой корень также равен нулю, и выполните возврат. Либо мы достигли взаимно нулевых листьев в обоих деревьях, что верно, либо одно является листом, а другое нет, что неверно. Это базовый случай.
  2. Если оба корня не равны нулю, убедитесь, что они имеют одинаковое значение, а затем рекурсивно проверьте как левое, так и правое поддеревья.

Вот код:

class TreeNode
  attr_accessor :val, :left, :right

  def initialize val, left = nil, right = nil
    @val = val
    @left = left
    @right = right
  end
end

def binary_tree_compare a, b
  return !a && !b if !a || !b
  return false if a.val != b.val
  return binary_tree_compare(a.left, b.left) &&
         binary_tree_compare(a.right, b.right)
end

a = TreeNode.new(
  1, TreeNode.new(
    2, TreeNode.new(4)
  ), TreeNode.new(3)
)
b = TreeNode.new(
  1, TreeNode.new(
    2, TreeNode.new(4)
  ), TreeNode.new(3)
)

puts binary_tree_compare a, b
12.04.2019

2

Код

def binary_tree_compare(a_top_node, b_top_node)
  convert(a_top_node) == convert(b_top_node)
end

def convert(node)
  { node.val => recurse(node) }
end

def recurse(node)
  return nil if node.left.nil? && node.right.nil?
  [node.left, node.right].each_with_object({}) do |n, h|
    h[n.val] = recurse(n) unless n.nil?
  end
end

Пример

Давайте сначала создадим два бинарных дерева. Они будут выглядеть следующим образом.

введите здесь описание изображения

Эти деревья кажутся одинаковыми по строению.

Это ваш класс TreeNode.

class TreeNode
  attr_accessor :val, :left, :right

  def initialize val, left = nil, right = nil
    @val = val
    @left = left
    @right = right
  end
end

Кроме того, я создам класс Tree.

class Tree
  attr_reader :top_node, :name_to_node

  def initialize(top_node_name)
    @top_node = TreeNode.new(top_node_name)
    @name_to_node = { top_node_name=>@top_node }
  end

  def add_node(name, parent, side)
    node = TreeNode.new(name)
    name_to_node[name] = node
    if side == :left
      name_to_node[parent].left = node
    else
      name_to_node[parent].right = node
    end
  end
end

Теперь мы можем построить два бинарных дерева, показанных на рисунке.

a = Tree.new(1)
a.add_node(2, 1, :left)
a.add_node(3, 1, :right)
a.add_node(4, 2, :left)
a.add_node(5, 3, :right)

a.top_node
  #=> #<TreeNode:0x000059e97fa499e0 @val=1,
  #     @left=#<TreeNode:0x000059e97fa508d0 @val=2,
  #       @left=#<TreeNode:0x000059e97fa719b8 @val=4, @left=nil, @right=nil>,
  #       @right=nil>,
  #     @right=#<TreeNode:0x000059e97fa66900 @val=3,
  #       @left=nil,
  #       @right=#<TreeNode:0x000059e97fa7cb60 @val=5, @left=nil, @right=nil>>> 

b = Tree.new(1)
b.add_node(2, 1, :right)
b.add_node(3, 1, :left)
b.add_node(4, 2, :right)
b.add_node(5, 3, :left)

b.top_node
  #=> #<TreeNode:0x000059e97fa99b48 @val=1,
  #     @left=#<TreeNode:0x000059e97fab5758 @val=3,
  #       @left=#<TreeNode:0x000059e97faf4cf0 @val=5, @left=nil, @right=nil>,
  #       @right=nil>,
  #     @right=#<TreeNode:0x000059e97faaf9e8 @val=2,
  #       @left=nil,
  #       @right=#<TreeNode:0x000059e97fac0040 @val=4, @left=nil, @right=nil>>> 

Теперь определите, равны ли эти два бинарных дерева по структуре.

binary_tree_compare(a.top_node, b.top_node)
  #=> true

Пояснение

convert возвращает следующие хэши.

convert(a.top_node)
  #=> {1=>{2=>{4=>nil}, 3=>{5=>nil}}} 
convert(b.top_node)
  #=> {1=>{3=>{5=>nil}, 2=>{4=>nil}}}

Эти хэши, которые представляют собой сопоставления двоичных деревьев 1-1, явно равны, даже если их ключи находятся в разном порядке.

13.04.2019
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..