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)
Related
I am doing Leet Code question 572. Subtree of Another Tree:
Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.
A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node's descendants. The tree tree could also be considered as a subtree of itself.
I had a working solution. However, when trying a slightly different approach, I ran into a problem with my recursive dfs function. The structure of my code is this:
def isSubTree(self, root, subRoot):
def dfs(root, subRoot):
# some function that returns True when certain conditions are met
if not root: return
self.isSubtree(root.left, subRoot)
self.isSubtree(root.right, subRoot)
if root.val == subRoot.val:
if dfs(root, subRoot):
return True
return False
Basically, isSubTree explores all the nodes in the tree. Once it finds a node with the same value as subRoot, it compares the sub tree rooted at that node with the sub tree rooted at subRoot with dfs().
I intended that when the dfs() function returns true, isSubTree() will also return true. If I've explored all the nodes in the tree (isSubTree() reaches the end) and dfs() hasn't returned true
at all, isSubTree() will return False.
However,my code always returns false seemingly because of the last line where it returns False (I've tested it and can verify that the return True part in if dfs() was reached, also I'm pretty sure my dfs() function is correct).
My question is, is there an elegant way to have my code do what I want it to do?
It is hard to see which code you are using, since obviously there is a syntax problem just below def dfs. Either the indentation is off or there is code missing (at the time of writing).
There are these issues:
The returned value from either recursive self.isSubTree calls is not used at all. This cannot be right, as certainly you need that information to conclude anything about the work done.
if not root: return will not return a boolean value when it kicks in. This should make the distinction between the case where also subTree is None: in that case the returned value should be True. Otherwise it should be False
Assuming your non-provided dfs code is correct, it will deal well with the previous point as well (where one or both of the arguments is None), and will compare the node values correctly, so then if not root should not be performed before dfs is called, as dfs will take care of that.
Similarly if root.val == subTree.val should not have to occur where it now occurs, but only in dfs.
Concluding, the working code could be like this:
class Solution(object):
def isSubtree(self, root, subRoot):
def dfs(root, subRoot):
if not root or not subRoot or root.val != subRoot.val:
return root == subRoot # Must both be None to have success
return dfs(root.left, subRoot.left) and dfs(root.right, subRoot.right)
return dfs(root, subRoot) or root and (
self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
)
Solved it with the following:
def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
def dfs(r1, r2):
# some function
if not root:
return False
if root.val == subRoot.val:
if dfs(root, subRoot):
return True
return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
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.
I'm trying to solve one algorithmic problem from leetcode.
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the depth of the two subtrees of every node
never differ by more than 1.
My approach is to collect the depths of the nodes and compare them. When the difference is smaller than 1 (abs), then return 1, else return False. When there is not root replace it with 0.
class Solution(object):
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root or not root.left and not root.right:
return 0
a = self.isBalanced(root.left)
b = self.isBalanced(root.right)
if abs(a-b)<=1:
return 1 + max(a,b)
else:
return False
return True
Unfortunately, the solution fails on a very primitive [] empty test input. Which is unclear to me. I thought that when there are no children, there's nothing to compare, hence 0. Am I missing smth from the definition of height-balanced 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)
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.