while statement with stack in Inorder Traversal - python

When I want to save all nodes into an inorder list sorted_node_val, I use while statement.
def closestKValues(self, root, target, k):
# write your code here
stack = []
sorted_node_val = []
node = root
while node:
stack.append(node)
node = node.left
while stack is not None:
node = stack.pop()
sorted_node_val.append(node.val)
if node.right:
node = node.right
while node:
stack.append(node)
node = node.left
However the code above yields error with while stack is not None: and the result is
File "/Users/Python/901.py", line 35, in closestKValues
node = stack.pop()
IndexError: pop from empty list
I changed while statement into while stack: and fixed this error.
But I wonder what's the difference between while stack is not None: and while stack:

At the very end of your stack, stack = []. This is an list of length 0, not a none object. You can verify this by trying None == [], which will be False.

You can check this condition out, by running a Python IDE and creating an empty array. Then, with the empty array, run a condition check:
temp = []
temp is None
The output is False.
This tells us that an empty array is not considered to be None, which makes sense because an array is not of a null type.

Related

Is it possible to repeat a method in a for loop?

so I am writing a code to find the height of a binary search tree. My first thoughts were to traverse through both the right and left subtrees, append the values of the nodes in each subtree to a list, and then get the length of the list, and the longer list would be the height of the tree. Here is my code:
def getHeight(self,root):
lstr = []
lstl = []
if root.right is not None:
lstr.append(root.right.data)
if root.right.right is not None:
lstr.append(root.right.right.data)
if not root.left == None:
lstl.append(root.left.data)
if root.left.left is not None:
lstr.append(root.left.left.data)
return lstr
return lstl
However, is it possible to use a for loop to keep iterating through the .right.right.right and just continue using the .right attribute in the if statement until the for loop ends?

Checking if a binary tree is symmetric around its centre- how to print node values as a debug?

I am writing code to solve the following leetcode problem:
https://leetcode.com/problems/symmetric-tree/
The problem in a nutshell is "Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center)."
from collections import deque
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
queue= deque()
if not root:
return []
#add left and right child of root to start (if root is not None)
if root.left:
queue.append(root.left)
if root.right:
queue.append(root.right)
right_subt = []
left_subt = []
while queue:
level_length = len(queue)
#iterate over each level of the tree and add left subtree to left_subt and right subtree to right_subt
for _ in range((level_length//2)+1):
node = queue.popleft()
left_subt.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
for _ in range((level_length-(level_length//2))+1):
node = queue.popleft()
right_subt.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
#compare left and right subtree at each level to check if they're the same
if left_subt !=right_subt.reverse():
return False
#reinitialize left and right subtree lists
left_subt = []
right_subt = []
return True
I have run the algorithm with the following input: [1,2,2,3,4,4,3] ; it is the input that you see at the top of the page when you click on the link to Leetcode above.
It is returning false when it should be returning true. When I run the input on paper it seems to work, but unlike arrays/strings, I am not sure how to print node values at each stage. Any ideas how to do this, or can someone please outline where the code falls short?
I am not sure how to print node values at each stage.
printing values in python is as easy as:
print(<something>)
where <something> is whatever you need to print
for debug purposes you can at any point in your code add for example:
print(node.val)
or
print(queue)
At least the following snippet will not work as you expected
for _ in range((level_length//2)+1):
node = queue.popleft()
left_subt.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
Right at the 1st loop, at which, level_length == 2 (assume that both root.left & root.right are not None )
-> (level_length//2)+1 will return (1 + 1)
-> The 1st for statement will loop two times, and consume both root.left & root.right in your queue before the 2nd for statement starts
-> nothing's left for your right_subt
-> In the 2nd for statement, queue.popleft() will throw an exception due to the fact that you tried to 'pop from an empty deque'

Leetcode 426. Convert Binary Search Tree to Sorted Doubly Linked List?

I am very confused about the question No.426 on leetcode, as I think my answer is right. But after running it shows I am wrong. Below is the question and my original answer:
"""
# Definition for a Node.
class Node:
def __init__(self, val, left, right):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root):
"""
:type root: Node
:rtype: Node
"""
if root:
sign = True
stack = []
node = root
while stack or node:
if node:
stack.append(node)
node = node.left
else:
node = stack.pop()
if sign:
pre,head = node, node
else:
pre.right = node
node.left = pre
pre = node
node = node.right
head.left = pre
pre.right = pre
return head
else:
return None
Could someone help me to figure out what's wrong with my codes? Any comment or suggestion will be so appreciated.
I see two problems with the code.
First is that inside your if sign: block you need to set sign = False since you only want to initialize head once and execute that block only the first time. (Not sure why the variable is called sign, perhaps first would be more appropriate, or just reusing a head = None for that condition would have worked too.)
The second bug is smaller and affects the last link in the list to make it circular. You want to set pre.right = head instead of pre, so that the last node of the list points back at the first, not at itself.
I haven't really tested this, so it's possible I'm missing something, but it looks to me that this should be enough to fix this code.

What is the input value of this OJ on leetcode(Binary Tree Level Order Traversal )?

It's a question from leetcode as linked here.
https://leetcode.com/problems/binary-tree-level-order-traversal/
So here is my code, but I really don't know what the input is and its relationship to TreeNode defined below.
Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# #param {TreeNode} root
# #return {integer[][]}
def levelOrder(self, root):
if not root:
return []
else:
printout, CurrLevel = [], [root]
while CurrLevel:
printout.extend(CurrLevel)
NextLevel = []
for item in CurrLevel:
temp = []
if item.left != None:
temp.append(item.left)
if item.right != None:
temp.append(item.right)
NextLevel = NextLevel.extend(temp)
CurrLevel = NextLevel
return printout
Input: [1,2]
Output: [[1,2]]
Expected: [[1],[2]]
So I met this finally, so what's the treenode anyway? Why does it appear like a list?
Well this is a OJ problem and I am just so unsure about the testing case, as I can't understand how the treenode presented here. As described in the problem, it seems there is only one "root" element is input each time.
I am confused because it seems that for each test case (each problem in leetcode contains tens or hundreds of test cases to test the validity of the program), only one TreeNode (named root) is inputted, if so, I could happily reference its .val, its .left or its .right, therefore a tree could be traversed up to down from the "root" element. BUT through the test case I see here (once the wrong solution is produced by the program, it produced a report, that's why I show the "input" [1, 2] presented here), I see a list, or at least list alike, which contains two elements. What I expected is only one TreeNode called root inputted here, but now I see a list. Clearly I know I am supposed to printout a list of lists, which differs to the confusion I raised up here.
So in [1, 2], I can't understand what 1 and 2 represent respectively, an integer? A treenode? Actually I think [1, 2] itself is a treenode where 1 and 2 stands for its .val, .left.
Importantly, my code is based on the assumption that each input is one node, and leave the [1,2,3](may stands for .val, .left, .right of the TreeNode) whatever input behind. I later found I did do something wrong and revised my code as follows:
class Solution:
# #param {TreeNode} root
# #return {integer[][]}
def levelOrder(self, root):
if not root:
return []
else:
printout, CurrLevel = [], [root]
while CurrLevel:
values = []
for node in CurrLevel:
values = values.append(node.val)
printout.append(values)
NextLevel = []
for item in CurrLevel:
temp = []
if item.left != None:
temp.append(item.left)
if item.right != None:
temp.append(item.right)
NextLevel = NextLevel.extend(temp)
CurrLevel = NextLevel
return printout
This time it seems the following bug occurs:
Input: [1]
Output: [null]
Expected: [[1]]
Well I have checked my code, and found that node.val produces 1 when Input:[1], while values produces [null]! That's so weird!

Assigning local variable in recursion

I have a tree and It is not a binary tree, so I want to compare all of the nodes and return the largest one, using recursion. I am having a problem of how to keep track of it, as I can't put a global variable, as it has to be local... I guess... But then if the recursion goes it resets the local variable.
def tree_max(node):
max=1
if node.left == None and node.right == None:
if node.value>max:
max=node.value
return max
elif node.left == None and node.right != None:
return tree_max(node)
elif node.left != None and node.right == None:
return tree_max(node.left)
else:
return tree_max(node.left)
Any suggestions?
You don't need to keep the maximum value in a variable across all recursive calls, and by all means, not a global one. In a well-structured recursion, the result will be passed around in the return value of each recursive call. Like this:
def tree_max(node):
maxleft = float('-inf') if not node.left else tree_max(node.left)
maxright = float('-inf') if not node.right else tree_max(node.right)
return max(node.value, maxleft, maxright)
The above assumes that node is not None, if node can be null then check for this condition before calling tree_max().
I'd have a generator that traverses the tree. This means you can write a min(), sum() etc without duplicating the traversal logic
def tree_traverse(node):
if not node.left and not node.right: # if only leaf nodes have values
yield node.value
if node.left:
for v in tree_traverse(node.left):
yield v
if node.right:
for v in tree_traverse(node.right):
yield v
now you can just use max(tree_traverse(node))
if all the nodes have values, you can skip the first if and dedent the yield
as #abarnert says, Python3.3 has a nice way to simplify recursive generators
def tree_traverse(node):
if not node.left and not node.right: # if only leaf nodes have values
yield node.value
if node.left:
yield from tree_traverse(node.left)
if node.right:
yield from tree_traverse(node.right)
This is usually done using key word arguments e.g.
def tree_max(node, max=None):

Categories