I am trying to solve a problem that requires finding the minimum depth of a binary tree. I can't seem to find the error. Any advice would be of great help.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
queue = []
queue = collections.deque(queue)
queue.append(root)
depth = 0
while len(queue) != 0:
numberOfNodes = len(queue)
while numberOfNodes > 0:
currentNode = queue.popleft()
if not currentNode and not currentNode:
depth += 1
return depth
if currentNode.left:
queue.append(currentNode.left)
if currentNode.right:
queue.append(currentNode.right)
numberOfNodes -= 1
depth += 1
return depth
I think I found the slight error. In place of :
if not currentNode and not currentNode:
depth += 1
return depth
Maybe, it should be this:
if currentnode.left is None and currentnode.right is None:
return depth
Related
I'm the beginner for python,and I always feel confused about binary tree when I practise in leetcode.
Here is my code:
from typing import Optional
#Definition for a binary tree node.(This is given by leetcode)
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def averageOfSubtree(self, root: Optional[TreeNode]) -> int:
ans = 0
def traverse(node):
if node is None:
return (0,0)
left = traverse(node.left)
right = traverse(node.right)
total = left[0] + right[0] + node.val
count = left[1] + right[1] +1
if total // count == node.val:
nonlocal ans
ans += 1
return (total, count)
traverse(root)
return ans
root = [4,8,5,0,1,None,6]
a = Solution()
print(a.averageOfSubtree(root))
The TreeNode definition is given by leetcode, and I just copy down and run on my vscode, however, it hint an error:AttributeError: 'list' object has no attribute 'left'
How can I modify it?
The logic I tried:
def min_tree_value(self):
while self.left:
self.left = self.left.left
return self.data
Actual Python program Logic:
def min_tree_value(self):
if self.left is None:
return self.data
return self.left.min_tree_value()
The actual Python program logic is in recursion form. I tried the same logic in While loop()
I'm not sure whether my logic is correct. Do help me to figure out the incorrect logic and point where I'm Wrong.
Your logic is almost there, but not quite:
def min_tree_value(self):
node = self
while node.left:
# don't change the structure by rebinding node.left,
# but iterate the tree by moving along nodes!
node = node.left
return node.data
Note that in the original code, you never reassign self before returning its value, so you always returned the root value.
First of all, the question asks about finding the minimum element in a binary tree.
The algorithm you used, will find the minimum element in the Binary Search Tree (as the leftmost element is the minimum).
For finding minimum element in a simple Binary Tree, use the following algorithm:
# Returns the min value in a binary tree
def find_min_in_BT(root):
if root is None:
return float('inf')
res = root.data
lres = find_min_in_BT(root.leftChild)
rres = find_min_in_BT(root.rightChild)
if lres < res:
res = lres
if rres < res:
res = rres
return res
Additions to the answer after OP changed the question:
The logic for the algorithm you tried is correct, with a small correction in the implementation: self = self.data. Both of them find the leftmost element.
I have also tested both the functions which return the same output:
class Node:
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def insert(self, data):
if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.data = data
def findval(self, lkpval):
if lkpval < self.data:
if self.left is None:
return str(lkpval)+" Not Found"
return self.left.findval(lkpval)
elif lkpval > self.data:
if self.right is None:
return str(lkpval)+" Not Found"
return self.right.findval(lkpval)
else:
print(str(self.data) + ' is found')
def PrintTree(self):
if self.left:
self.left.PrintTree()
print( self.data),
if self.right:
self.right.PrintTree()
def min_tree_value_original(self):
if self.left is None:
return self.data
return self.left.min_tree_value_original()
def min_tree_value_custom(self):
while self.left:
self = self.left
return self.data
root = Node(12)
root.insert(6)
root.insert(14)
root.insert(3)
root.insert(3)
root.insert(1)
root.insert(0)
root.insert(-1)
root.insert(-2)
print(root.min_tree_value_original())
print(root.min_tree_value_custom())
Output:
-2
-2
Here -2 is the smallest and the leftmost element in the BST.
I have written a class called Node with certain functions to create a binary search tree. All of the functions work correctly except the function height() that is supposed to calculate the height of the BST. It returns a very small number compared to what I was expecting it too given that I haven't balanced the tree. The number I was expecting was close to N where N is the amount of numbers I have entered in the tree. Here is the code:
from __future__ import print_function
import random
class Node(object):
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def insert(self, data):
if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.data = data
def lookup(self, data, parent=None):
if data < self.data:
if self.left is None:
return None, None
return self.left.lookup(data, self)
elif data > self.data:
if self.right is None:
return None, None
return self.right.lookup(data, self)
else:
return self, parent
def delete(self, data):
node, parent = self.lookup(data)
if node is not None:
children_count = node.children_count()
if children_count == 0:
if parent:
if parent.left is node:
parent.left = None
else:
parent.right = None
else:
self.data = None
elif children_count == 1:
if node.left:
n = node.left
else:
n = node.right
if parent:
if parent.left is node:
parent.left = n
else:
parent.right = n
else:
self.left = n.left
self.right = n.right
self.data = n.data
else:
parent = node
successor = node.right
while successor.left:
parent = successor
successor = successor.left
node.data = successor.data
if parent.left == successor:
parent.left = successor.right
else:
parent.right = successor.right
def compare_trees(self, node):
if node is None:
return False
if self.data != node.data:
return False
res = True
if self.left is None:
if node.left:
return False
else:
res = self.left.compare_trees(node.left)
if res is False:
return False
if self.right is None:
if node.right:
return False
else:
res = self.right.compare_trees(node.right)
return res
def print_tree(self):
if self.left:
self.left.print_tree()
print(self.data, end=" ")
if self.right:
self.right.print_tree()
def height(self, root):
if root is None:
return 0
else:
return max(self.height(root.left), self.height(root.right)) + 1
random.seed(3)
bst = Node(random.randint(1,1000))
for i in range(1,80000,1):
bst.insert(random.randint(1,1000))
print(bst.height(bst))
You are getting low answer because you are always inserting number from 1 to 1000 only so the numbers existing are always remains same and you are thinking you are inserting 1,80000 numbers but actually because of generating randomly the same numbers from 1 to 1000 you are actually inserting just 1000 values from 1 to 1000 maximum.
Wrong Code
bst = Node(random.randint(1,1000))
for i in range(1,80000,1):
bst.insert(random.randint(1,1000))
print(bst.height(bst))
Modification
bst = Node(random.randint(1,80000))
for i in range(1,80000,1):
bst.insert(random.randint(1,80000))
print(bst.height(bst))
Your code is working fine you can execute below code and check it with the image below
bst = Node(7)
list1 = [3,11,1,5,9,13,4,6,8,12,14,8.5]
for i in list1:
bst.insert(i)
print(bst.height(bst))
bst.print_tree()
Ouput
5
1 3 4 5 6 7 8 8.5 9 11 12 13 14
You should declare as sorted array to get maximum height for binary search tree.
but this may not work for larger numbers as 1000 or 10,000 . It will work fine for 500 elements because of your recursion for insertion may exceed the maximum recursion depth in python
UPTO 500
bst = Node(0)
list1 = list(range(1,500,1))
for i in list1:
bst.insert(i)
print(bst.height(bst))
OUTPUT
499
1000 elements
bst = Node(0)
list1 = list(range(1,500,1))
for i in list1:
bst.insert(i)
print(bst.height(bst))
OUTPUT
self.right.insert(data)
self.right = Node(data)
RecursionError: maximum recursion depth exceeded
I am confuse, what is the different in code for depth and height in binary search tree?
I did a google to check on the code for depth, as well as the code for height.
It kind of turn out to be the same.
Can someone tell me the differences?
Anyway, below is my code for height as well as depth.
But my depth isn't working.
def height(self,key):
node = self.root
while node is not None:
if node.key == key:
return self.height2(node)
elif node.key > key:
node = node.left
else:
node = node.right
def height2(self,n):
if n is None:
return -1
else:
#return the max
return 1 + max(self.height2(n.left),self.height2(n.right))
For the depth
def depth(self,node):
node = self.root
if node.left == None and node.right == None:
return 1
elif node.left == None:
return node.right.depth() + 1
elif node.right == None:
return node.left.depth() + 1
else:
return 1 + max(self.depth(node.left),self.depth(node.right))
Edited for depth:
def depth(self,key):
temp = self.root
while temp is not None:
if temp.key == key:
return temp.val
elif temp.key > key:
temp = temp.left
else:
temp = temp.right
return return 1 + max(self.depth(node.left),self.depth(node.right))
Depth is a value associated to a single node in a tree, it's the number of edges from a node to root node. Root node has a depth of 0. Height on the other hand is the longest path from a node to root, i.e. max depth of any node in the tree.
The code you have seem to work just fine, height2 is enough to determine the the height of a tree. If you need determine a depth of a node you'd need to first find it.
Assuming the tree is BST then following code would return the depth or -1 if the key is not in the tree:
class Node(object):
def __init__(self, key):
self.key = key
self.left = None
self.right = None
def depth(root, key, current_depth=0):
if not root:
return -1
elif root.key == key:
return current_depth
elif key < root.key:
return depth(root.left, key, current_depth + 1)
else:
return depth(root.right, key, current_depth + 1)
root = Node(3)
root.left = Node(2)
root.left.left = Node(1)
for i in xrange(1, 4):
print 'key: {0}, depth: {1}'.format(i, depth(root, i))
# key: 1, depth: 2
# key: 2, depth: 1
# key: 3, depth: 0
path = 0 # the lenght of the path
while self.right != None or self.left != None:
while self.right != None:
self = self.right
path = path +1
while self.left != None:
self = self.left
path = path +1
return path
this is my sample code for find the Height, is defined as the length of the
longest path by number of nodes from self to a leaf. The height of a leaf node is 1.
it doesn't work.
What you're doing isn't recursive, it's iterative.
Recursive would be something like:
def height(node):
if node is None:
return 0
else:
return max(height(node.left), height(node.right)) + 1
You were given the solution by mata, but I suggest you also look at your code and understand what it is doing:
while self.right != None:
self = self.right
path = path +1
What will this do? it will find the right child, then its right child, and so on. So this checks only one path of the "rightmost" leaf.
This does the same for the left:
while self.left != None:
self = self.left
path = path +1
The idea in recursion is that for each subproblem, you solve it using the exact same recipe for all other subproblems. So if you would apply your algorithm only to a subtree or a leaf, it would still work.
Also, a recursive definition calls itself (although you can implement this with a loop, but that is beyond the scope here).
Remeber the definition:
Recursion: see definition of Recursion.
;)
def height(node):
if node is None:
return 0
else:
if node.left==None and node.right==None:
return max(height(node.left), height(node.right))+0
else:
return max(height(node.left), height(node.right))+1
If you consider each increasing edge to be the height.
To pass hackerrank testcases
def getHeight(self, root):
if root == None:
return -1
else:
return 1 + max( self.getHeight(root.left), self.getHeight(root.right) )
Here is the complete program in Python ::
class Node :
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def maxDepth(node):
if node is None :
return 0
else :
ldepth = maxDepth(node.left)
rdepth = maxDepth(node.right)
if (ldepth>rdepth):
return ldepth +1
else :
return rdepth +1
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
print "Height of tree is %d" %(maxDepth(root))
Source : here
def height(self):
if self.root !=None:
return self._height(self.root,0)
else:
return 0
def _height(self,cur_node,cur_height):
if cur_node==None :
return cur_height
left_height = self._height(cur_node.left_child,cur_height+1)
right_height = self._height(cur_node.right_child,cur_height+1)
return max(left_height,right_height)