4

Given two trees, I want to return true if they are equal in structure and in value and false otherwise.

Given the following class:

class TreeNode
  attr_accessor :val, :left, :right

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

complete the function

def binary_tree_compare(a, b)

My research led me to here. I have tried the ruby solution but to no avail Below is the code I have tried so far:

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

I expect the output to be true if TreeNodes a and b are equal in structure and in value and false otherwise.

I am getting a syntax error and this is the stack trace:

  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
    ^~~ ```
Esseme
  • 179
  • 1
  • 12

2 Answers2

2

First, let's fix the syntax/logic errors:

  1. Use parentheses to enforce operator precedence:

    while a,b = for_check.shift
    

    should be

    while (a, b = for_check.shift)
    
  2. The array for_check doesn't exist when you try to push an element onto it.

    for_check << [a, b]   
    

    should be

    for_check = [a, b]   
    

Secondly, your code doesn't seem to have much to do with the problem presented (although the simultaneous search using both nodes in a stack is the right idea). For one, the TreeNode class you've shown here has no children member array. The intention of that code is to handle general trees with n children as well as to ignore the ordering of those children, two characteristics that are not part of the problem you're facing.

My recommendation is to re-approach the problem assuming a binary tree and ordering of children matters as well as their values.

If you'd like a spoiler, try the following recursive logic (iterative works too, as you're doing with an explicit stack, and it's instructional to write both):

  1. If either root is nil, make sure the other root is also nil and return. We've either reached mutually nil leaves in both trees, which is valid, or one is a leaf and the other isn't, which is invalid. This is the base case.
  2. If both roots are non-nil, ensure they have the same value, then recursively validate both left and right subtrees.

Here's the code:

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
ggorlen
  • 44,755
  • 7
  • 76
  • 106
0

Code

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

Example

Let's first create two binary trees. They will look like the following.

enter image description here

These trees are seen to be equal in structure.

This is your class TreeNode.

class TreeNode
  attr_accessor :val, :left, :right

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

In addition, I will create a class 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

We can now construct the two binary trees shown in the drawing.

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>>> 

Now determine if these two binary trees are equal in structure.

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

Explanation

convert returns the following hashes.

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

These hashes, which are 1-1 mappings of the binary trees, are clearly equal even though their keys are not in the same order.

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100