None Result Issue (Binary Tree) - python

I have a homework problem and I would really be grateful if someone can give me some help with my learning.
This is the question:
#One concept you will encounter in future CS class is the
#idea of a binary tree.
#
#A binary tree is made of nodes. Each node has three
#attributes: its own value, a left branch, and a right branch.
#The left branch will be lower than the node's own value, and
#the right branch will be higher than the node's own value.
#
#Some nodes will not have any branches; these are called leaf
#nodes. They only have their own value. Some nodes may have
#only one branch as well.
#
#Every binary tree has a single root node at the top of the
#tree. Most algorithms that operate on the tree will start at
#this root node.
#
#For example, let us imagine a binary tree with seven nodes.
#The top node's value is 10. The top node has two child nodes:
#the left node's value is 5, lower than 10. The right node's
#value is 15, higher than 10. Then, the left node has its own
#left and right nodes, with values 3 and 7: the lower and higher
#than 5 respectively, but both lower than 10 because they come
#from the original node's left (lower) branch. The right node's
#left and right branches have values 12 and 18, again lower
#and higher than 15 but both higher than 10.
#
#Below is the code for a single node. Right function called
#binary_tree_search. binary_tree_search should take two
#parameters: a single node, and a search value. It should return
#True if the search value is found anywhere in the tree with
#the node at the top, and False if the search value is not found.
#
#To do this, you'll want to write a function that goes down the
#tree similar to a binary search. If the search value is lower than
#the current node's value, it should continue searching to the
#left. If the search value is higher than the current node's value,
#it should continue searching to the right. If the search value is
#equal to the current node's value, it should return True. If the
#current node has no children (both left and right are None), it
#should return False as it has reached the bottom of the tree.
#
#You may assume that no two nodes will have the same value, and that
#every node will have either two children or none. You should not
#assume that the tree will have 7 nodes; it may have 3, 7, 15, 31,
#or more.
#
#HINT: Try breaking this into cases. What do you do if the node
#has the right value? What if the node is none? What if the node's
#value is higher than the search term? What if it's lower?
#
#HINT 2: To get around not knowing how big the tree will be,
#think about a process you can repeat over and over until either
#you find the search term or reach a leaf node. To repeat that
#process, you'd apply the same reasoning each time, just changing
#what node you're looking at.
class Node:
def __init__(self, value, left = None, right = None):
self.value = value
self.left = left
self.right = right
#Write your binary_tree_search function here!
And here is my code:
def binary_tree_search(node, node_value):
#print(node.value)
if node is None:
return False
elif node.value is node_value:
return True
elif node_value < node.value:
#print("This is the left node: ", node.left.value)
binary_tree_search(node.left, node_value)
elif node_value > node.value:
#print("This is the right node: ", node.right.value)
binary_tree_search(node.right, node_value)
else:
return False
These are the test cases:
#Below are some lines of code that will test your function.
#You can change the value of the variable(s) to test your
#function with different inputs.
#
#If your function works correctly, this will originally
#print: True, True, True, True, False, False, False
#(each on a separate line)
root_node = Node(10)
root_node.left = Node(5)
root_node.right = Node(15)
root_node.left.left = Node(3)
root_node.left.right = Node(7)
root_node.right.left = Node(12)
root_node.right.right = Node(18)
print(binary_tree_search(root_node, 18))
print(binary_tree_search(root_node, 7))
print(binary_tree_search(root_node, 15))
print(binary_tree_search(root_node, 10))
print(binary_tree_search(root_node, 1))
print(binary_tree_search(root_node, 11))
print(binary_tree_search(root_node, 21))
Here are the expected results
True
True
True
True
False
False
False
Here are my actual results:
None
None
None
True
None
None
None

you successfully implement recursion in two of the if cases, however you forget to return the result of this recursion:
add a "return " before each of the cases and everything should work:
# [...]
elif node_value < node.value:
#print("This is the left node: ", node.left.value)
return binary_tree_search(node.left, node_value)
elif node_value > node.value:
#print("This is the right node: ", node.right.value)
return binary_tree_search(node.right, node_value)
Elsewise, python sees no return statement for these cases and defaults to a return value of none (see e.g. Why does my recursive function return None?)

Related

trying to understand node exists in binary tree (recursion func) in python

I am trying to understand below recursion function which says whether a particular node exists in a binary tree. I did my homework and got most of the recursion part but the last return statement (return root.value == value or inleft or inright) bothers me.
can someone please help me in understanding this method?
def existsInTree(self, root, value):
if root is None:
return False
else:
inleft = self.existsInTree(root.left, value)
inright = self.existsInTree(root.right, value)
print(inleft,inright)
return root.value == value or inleft or inright
example binary tree:
10
/ \
11 9
we will first compare data of root with data of node to be searched. If the match is found, set the flag to true. Else, search the node in left subtree and then in the right subtree.
There's another way of looking at that return statement, you can split the return statement at the or keyword
def ifRootExists(self,root, value):
if (root == None):
return False
if (root.value == value):
return True
""" then recur on left sutree """
res1 = ifrootExists(root.left, value)
# root found, no need to look further
if res1:
return True
""" root is not found in left,
so recur on right subtree """
res2 = ifrootExists(root.right, value)
return res2
We can get the result from the above function whether some node exists.
The algorithm is as follows.
root is None or Not. If None, get back the position which the parent function called with the value of "False".
Otherwise, the function continuously search based on the current node.
inleft is a value of function "existsInTree" in which the current node's left child is the root node.
inright is a value of function "existsInTree" in which the current node's right child is the root node.
Let's assume that we want to search value as called V.
Which V exists in the tree means the current value is V or in the left tree, or in the right tree.
To summarize, inleft and inright means whether V includes or not in the subtree.

Wrong Answer in 'Is this a Binary Search Tree' on HackerRank

For the purposes of this challenge, we define a binary tree to be a binary search tree with the following ordering requirements:
The value of every node in a node's left subtree is less than the data value of that node.
The value of every node in a node's right subtree is greater than the data value of that node.
Given the root node of a binary tree, can you determine if it's also a binary search tree?
Complete the function in your editor below, which has parameter: a pointer to the root of a binary tree. It must return a boolean denoting whether or not the binary tree is a binary search tree. You may have to write one or more helper functions to complete this challenge.
Input Format
You are not responsible for reading any input from stdin. Hidden code stubs will assemble a binary tree and pass its root node to your function as an argument.
Constraints:
0<=data<=10^4
Output Format
You are not responsible for printing any output to stdout. Your function must return true if the tree is a binary search tree; otherwise, it must return false. Hidden code stubs will print this result as a Yes or No answer on a new line.
My Code:
""" Node is defined as
class node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
"""
def check_binary_search_tree_(root):
if root is None or (root.left is None and root.right is None):
return True
if root.left.data>=root.data or root.right.data<=root.data:
return False
check_binary_search_tree_(root.left)
check_binary_search_tree_(root.right)
return True
Why am I getting Wrong Answer?
The problem with your code is
first you didn't do :
return check_binary_search_tree_(root.left) and check_binary_search_tree_(root.right)
next even if you do that, you are forgetting to keep the root's value in mind while checking the BST property for left and right children. It could be that your left child is totally a good BST but it fails to be a BST when you consider its parent. Look at the below example:
6
4 7
2 8
The subtree rooted at 4 is a good BST but fails when you consider its root's value of 6.
The solution is then to check the proper range of values at each node i.e.
left_limit < root.data < right_limit
You could write your function as :
def check_binary_search_tree_(root, min = -math.inf, max = math.inf):
if root is None:
return True
if root.data > min and root.data < max:
return check_binary_search_tree_(root.left, min, root.data) and check_binary_search_tree_(root.right, root.data, max)
return False
check_binary_search_tree_(root.left)
check_binary_search_tree_(root.right)
You don't return a result of these recursive functions. Try to do:
return check_binary_search_tree_(root.left) and check_binary_search_tree_(root.right)
Full code example that works:
def check_binary_search_tree_(root):
def isValid(node, lower=float('-inf'), upper=float('inf')):
if not node:
return True
if node.data <= lower or node.data >= upper:
return False
return isValid(node.left, lower, node.data) and isValid(node.right, node.data, upper)
return isValid(root)

Find minimum depth of binary tree solution does not work when one side of tree is null

I am trying to understand why my solution to find the minimum depth of binary tree does not work when one side of the tree is None.
There's already a question asked on this here - Why won't my solution work to find minimum depth of a binary tree? but the answer there still does not make me understand.
My implementation code is as below.
class Solution:
def minDepth(self, root: 'TreeNode') -> 'int':
if root is None:
return 0
left = self.minDepth(root.left)
right = self.minDepth(root.right)
min_depth = min(left, right)
return 1 + min_depth
When the last line is modified to the following, it works.
if left == 0 or right == 0:
return 1 + left + right
return 1 + min_depth
My question is, why do you need to check if one side is None or not if in the end, you sum them all up anyway - return 1 + left + right?
Test case is
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
# [1, 2]
root = TreeNode(1)
root.left = TreeNode(2)
solution = Solution()
solution.minDepth(root)
My code returns 1 where it should return 2.
EDIT
The depth of the tree is defined as the number of nodes in the shortest path from the root of the tree to a leaf node.
When you are at a node that has only one child, then in your first code version, the min_depth for that node will be 0 (since one of the recursive calls will return 0).
That is indeed wrong, because the node is not a leaf. It would only be correct if the node were a leaf (without children).
In your example, the root is such a node (with one child). This is what happens:
minDepth(root) is called
....minDepth(root.left) is called
........minDepth(root.left.left) is called and returns 0, because it isNone`
........minDepth(root.left.right) is called and returns 0, because it isNone`
........min_depth = min(left, right) evaluates to 0
........the return value is 1 for minDepth(root.left)
....minDepth(root.right) is called and returns 0, because it is None
....min_depth = min(left, right) evaluates to 0, which is wrong.
....the final return value is thus 1 (wrong).
When you are in the situation where either left or right is 0, you need to get the minDepth of the remaining child and add 1 to it. That is why it works when you add this:
if left == 0 or right == 0:
return 1 + left + right

Function finding the deepest sum of a binary search tree

I'm trying to make a function in python were I don't want to change the BST class at all to do this. The function is to find the sum of the path of the root to the node with the highest depth. If there is multiple nodes that have the same depth I'm looking for the maximum sum of that and return it.
What I got so far (Using a basic BST Class)
class BTNode(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
After trying to make an algorithm to solve this for a while, I came up with a couple above but they were fails and I didn't know how to code it.
ALGORITHM:
I think this would work:
We start from the root. (The base case I think should be whenever we hit a leaf as in when there is no child in a node so no left or right child, and also when there is a left no right, or when there is a right no left)
I check the left subtree first and get the depth of it, we'll call it depth_L as well with the sum. Then I check the right subtree and we will call it depth_R then get the depth of it and its sum.
The second condition would be to check if they are equal, if they are equal then its easy and we just take the max sum of either two depths. Else we would see who has the highest depth and try to get the sum of it.
Now were I don't know how to do is a couple things.
1: I never learned optional parameters so I'm trying to avoid that while trying this exercise but I don't think I can and I'd really appreciate someone could show me some cool helper functions instead.
2: Its not the total sum of the right side or the left side its the path that I need. Its kind of confusing to think of a way to get just the path
(Heres my renewed attempt using the algorithm above):
def deepest_sum(self, bsum = 0, depth = 0):
# The root is in every path so
bsum = bsum + self.data
depth = depth + 1
# Base case whenever we find a leaf
if self.left == None and self.right == None:
result = bsum,depth
elif self.left is not None and self.right is None:
pass
elif self.left is None and self.right is not None:
pass
else:
# Getting the left and right subtree's depth as well as their
# sums, but once we hit a leaf it will stop
# These optional parameters is messing me up
if self.left:
(sums1, depth_L) = self.left.deepest_sum(bsum,depth)
if self.right:
(sums2, depth_R) = self.right.deepest_sum(bsum,depth)
# The parameter to check if they are equal, the highest goes through
if depth_L == depth_R:
result = max(sums1, sums2), depth_R
else:
if depth_L > depth_R:
result = sums1, depth_L
else:
result = sums2, depth_R
return result
Stuck on the parts i mentioned. Heres an example:
>>> BST(8, BST(7, BST(10), BST(11)), BST(6, BST(11), BST(9, None, BST(14)))
37 (depth 3 is the highest so 8 + 6 + 9 + 14 is the path)
Sorry i put BST i just forgot, its a binary Tree not BST.
I know mine gives a tuple but I can always make a helper function to fix that, I just thought it'd be easier keeping track of the nodes.
You could simplify the implementation quite a bit if the function doesn't need to be a method of BTNode. Then you could keep track of the depth & sum, iterate past the leaf and return the current depth and sum. Additionally if you return (depth, sum) tuples you can compare them directly against each other with max:
class BTNode(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def deepest_sum(node, depth=0, current=0):
# Base case
if not node:
return (depth, current)
depth += 1
current += node.data
return max(deepest_sum(node.left, depth, current),
deepest_sum(node.right, depth, current))
tree = BTNode(8, BTNode(7, BTNode(10), BTNode(11)), BTNode(6, BTNode(11), BTNode(9, None, BTNode(14))))
print(deepest_sum(tree))
Output:
(4, 37)

Determine if a binary tree rooted at a node is a max-heap [duplicate]

This question already has answers here:
How to test multiple variables for equality against a single value?
(31 answers)
Closed 8 years ago.
I'm trying to determine if a binary tree rooted at a node is a max-heap, and to do so I followed the rules of the heap property for a max-heap which states:
Max-heap:
All nodes are either greater than or equal to each of its children
My Idea of the implementation:
If at the node given as the parameter of is_max_heap has no right or left node than return True
Otherwise, if the value of the node is greater than the value of the left and right node, then call the function again on both the right and left nodes.
Return False otherwise.
My code:
class BTNode:
'''A generic binary tree node.'''
def __init__(self, v):
'''(BTNode, int) -> NoneType
Initialize a new BTNode with value v.
'''
self.value = v
self.left = None
self.right = None
def is_max_heap(node):
'''(BTNode) -> bool
Return True iff the binary tree rooted at node is a max-heap
Precondition: the tree is complete.
'''
if node.left and node.right is None:
return True
else:
if node.value > node.left.value and node.value > node.right.value:
return is_max_heap(node.left) and is_max_heap(node.right)
else:
return False
if __name__ == '__main__':
l1 = BTNode(7)
l2 = BTNode(6)
l3 = BTNode(8)
l1.left = l2
l1.right = l3
print(is_max_heap(l1))
So, under if __name__ == '__main__': I created three nodes, with values, 7, 6, and 8. The first node has a left and right node. So the tree would look like this:
7
/ \
6 8
This does not satisfy the max-heap property so it should return False. However running my code returns True and I can't figure out where I might of went wrong. If anyone can help me that would be really appreciated.
You have not thought of the case when there is only one child. Make sure your program works right on these two trees, too - one is a min heap, the other is a max heap:
2 1
/ /
1 2
Also learn to set brackets correctly; you have made the classic mistake True and 42 == 42; which is True.
Consider handling the two maybe-nonexistant childs the same way.
if left is not None:
if not <check max heap property for left subtree>: return False
if right is not None:
if not <check max heap property for right subtree>: return False
return True
The missing function should compare to the current node and recurse into the subtree if necessary.

Categories