How to traverse a tree with only one line? (python, tree traversal) - python

For a binary tree, we can traverse it in one line just like this (inorder, preorder, postorder is all ok):
# 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
# this is a preorder traversal with one line:
class Solution:
def preorderTraversal(self, root) -> List[int]:
return [] if root is None else [r.val] + self.preorderTraversal(r.left) + self.preorderTraversal(r.right)
For a tree that has multi-child in its node, how to complete the traversal work in one line?
I think list comprehension is a possible method, but I cannot complete the work in one line.
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def preorder(self, root: 'Node') -> List[int]:
if root is None: return []
ans = [root.val]
[ans.extend(x) for x in [self.preorder(child) for child in root.children]]
return ans
# This is a normal traversal:
# class Solution:
# def preorder(self, root: 'Node') -> List[int]:
# if root is None: return []
# ans = [root.val]
# for child in root.children:
# ans += self.preorder(child)
# return ans

Use a list comprehension to gather the traversal of all the root's children, regardless of how many children there are.
class Solution:
def preorderTraversal(self, root) -> List[int]:
# Original hard-coded approach for binary trees
# return [] if root is None else [r.val] \
# + self.preorderTraversal(root.left) + self.preorderTraversal(root.right)
# Generalized approach for binary trees
# return [] if root is None else [r.val] \
# + [y for child in [root.left, root.right] for y in self.preorderTraversal(child)]
# Generalized approach for a tree with arbitrary children per node
return [] if root is None else ([root.val]
+ [y for child in root.children for y in self.preorderTraversal(child)])

It could work like this:
class Solution:
def preorder(self, root):
return [] if root is None else [root.val] + [value
for child in (root.children or [])
for value in self.preorder(child)]
The idea is that list comprehension replaces a repeated call to append, not to extend. The non-comprehension code, that maps to the above list comprehension version, is:
class Solution:
def preorder(self, root):
if root is None:
return []
res = [root.val]
for child in (root.children or []):
for value in self.preorder(child):
res.append(value)
return res

Related

Python Leetcode BST: Level Order Traversal

I am trying to solve the Leetcode problem: 102. Binary Tree Level Order Traversal and hit a snag. My code below does not give the correct output and I have been trying to figure out what is the issue since it is not appending the last level in the tree. I would appreciate it someone can assist in making this code work.
# 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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
while not root:
return []
queue = [root]
result = [[queue[0].val]]
while queue:
nodes = queue
level_nodes = []
temp = []
for node in nodes:
level = queue.pop(0)
if node.left:
level_nodes.append(level.left.val)
temp.append(node.left)
if node.right:
level_nodes.append(level.right.val)
temp.append(node.right)
queue = temp
result.append(level_nodes)
return result
Input: root = [3,9,20,null,null,15,7]
Expected Output: [[3],[9,20],[15,7]]
Output I am getting: [[3],[9,20],[]]
Reference: https://leetcode.com/problems/binary-tree-level-order-traversal/description/
I have been able to solve the problem and leave it for reference anyone who is doing it in this way (Not trying to use deque from collisions library). This solution was accepted by LeetCode.
# 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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
while not root:
return []
queue = [root]
result = []
while queue:
level_nodes = []
temp = []
for node in queue:
level_nodes.append(node.val)
if node.left:
temp.append(node.left)
if node.right:
temp.a bppend(node.right)
queue = temp
result.append(level_nodes)
return result

Python. I am trying to iteratively perform inorder Traversal of a tree, but I am going into an infinite loop

Below in the solution class, I have an implementation of an inorder traversal (left, root, right).
For some reason I am entering into an infinte loop and I wonder if it is becaue of the way python handels consecutive if if/else statements?
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = righ
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
out = []
stack = []
if root is None:
return out
else:
stack.append(root)
while stack != []:
temp = stack.pop()
if temp.right:
stack.append(temp.right)
if temp.left:
a = temp.left
stack.append(temp)
stack.append(a)
else:
out.append(temp.val)
return out

Binary Tree Level Order Traversal in Python

Given the following tree:
I should return the level order traversal of the tree from left to right:
so the above example would output a list of lists :
[ [3], [9,20], [15,7] ]
I wrote the following code, idea is storing the node value and its depth recursively in a Queue then iterate the Queue tuples and put the in intermediate list O if no more node of same depth append O to output and empty O and so on. However my code Timeout any help?
import queue
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
def helper(root,res,level):
if not root:
return res
l=level+1
res.put((root.val,level))
helper(root.left,res,l)
helper(root.right,res,l)
res=queue.Queue()
helper(root,res,0)
d=1
output=[]
node,depth=res.get()
output.append([node])
while res:
o=[]
node,depth=res.get()
while d ==depth:
o.append(node)
node,depth=res.get()
else:
d+=1
output.append(o)
return output
Here is my code for the Breadth First Search (BFS) Iterative Implementation with nodes in each level in the final output is under a single list:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def BFS(self, root) -> int:
level=1
current=(root, level)
s=set()
result=[]
Q = [current]
while Q:
current=Q.pop()
level=current[1]
if current[0] not in s:
result.append([current[0].val, level])
s.add(current[0])
if current[0].left:
Q.insert(0,(current[0].left, level+1))
if current[0].right:
Q.insert(0,(current[0].right, level+1))
output=[]
temp=[]
level=1
for val in result:
if val[1]==level:
temp.append(val[0])
elif val[1] > level:
output.append(temp)
temp=[val[0]]
level+=1
output.append(temp)
return output
Testing:
n1=TreeNode(3)
n2=TreeNode(9)
n3=TreeNode(20)
n4=TreeNode(6)
n5=TreeNode(15)
n6=TreeNode(7)
n1.left=n2
n1.right=n3
n2.left=n4
n3.left=n5
n3.right=n6
sol1=Solution()
print(sol1.BFS(n1))
[[3], [9, 20], [6, 15, 7]]
Thanks for the answer from san. The solution helps me solve problem 107 of leetcode. I revised a little bit based on my understanding. There are two ways to solve this question but I prefer to use BFS fashion. This revised version compresses both value and level in the queue. It provides more flexibility comparing with only print the value of each node in the tree, as other tutorials provided.
# 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 levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
if root is None:
return None
level = 1
q = []
q.append((root,level)) # push both node and level.
save = []
while q:
cur = q.pop(0)
cur_node = cur[0]
cur_level = cur[1]
# print(cur_node.val)
# print(cur_level)
save.append([cur_node.val, cur_level])
if cur_node.left:
q.append((cur_node.left, cur_level+1))
if cur_node.right:
q.append((cur_node.right, cur_level+1))
print(save) # once print, you will have the idea about how to reorgnized the required output.
level = 1
output = []
temp = []
for i in range(len(save)):
cur = save[i]
#print(cur)
if cur[1] == level:
temp.append(cur[0])
if cur[1] != level:
output.insert(0, temp)
temp = []
temp.append(cur[0])
level = level + 1
if i == len(save)-1:
output.insert(0, temp)
return output
You can use the below logic , to print out nodes in BFS .
If you also need , you modify the method to return a list as well .
def levelOrder(root):
qroot = []
print(root.info,end=' ')
if root.left:
qroot.append(root.left)
if root.right:
qroot.append(root.right)
while(qroot):
tmp = qroot[0]
if tmp.left:
qroot.append(tmp.left)
if tmp.right:
qroot.append(tmp.right)
print (tmp.info,end=' ')
qroot.pop(0)
return
Instead of printing the values , you can directly keep appending the value to a new list and return the same .

How to return a list of lists in recursive function in Python

I am playing around with some toy code in Python. But somehow cant get through. I am using a recursion in a Tree data structure to generate paths from a particular node to each children leaf nodes.
The idea behind the recursive function is to have a list which would collect each path to the individual leaf node and then collect each paths in another list.
class Tree:
def __init__(self):
self._ancestors = []
self._store_nodes = {}
def add_node(self, node):
assert isinstance(node, Node)
self._store_nodes[node.name] = node
def get_c_path(self, node):
subpath = []
path = []
path = self.ret_path(node, subpath, path)
return path
## recursive function to fetch paths
def ret_path(self, node, subpath=[], pathstore=[]):
if len(node.children) == 0:
pathstore.append(subpath)
return
else:
for c in node.children:
subpath.append(c)
self.ret_path(c, subpath, pathstore)
class Node(object):
def __init__(self, name=''):
self._name = name
self._children = set([])
self._parents = set([])
#property
def name(self):
return self._name
#property
def children(self):
return self._children
#property
def parents(self):
return self._parents
def add_child(self, node):
assert isinstance(node, Node)
self._children.add(node)
def add_parent(self, node):
assert isinstance(node, Node)
self._parents.add(node)
if __name__ == '__main__':
node_store = {1 : [2,3,4,5,6], 6 : [7,2,8,9,5], 2 : [10,11,5], 12 : [13,14,15,16], 5 : [21,22,23]}
tree = Tree()
## build the tree and set parents and children of each node
for k, v in node_store.items():
parent_node = None
if k in tree._store_nodes:
parent_node = tree._store_nodes[k]
else:
parent_node = Node(k)
tree.add_node(parent_node)
for c in v:
child_node = None
if c in tree._store_nodes:
child_node = tree._store_nodes[c]
else:
child_node = Node(c)
tree.add_node(child_node)
parent_node.add_child(child_node)
child_node.add_parent(parent_node)
print '-------------'
path = tree.get_c_path(tree._store_nodes[2])
for p in path:
for t in p:
print t.name
print "-----"
The result I am expecting is a list of list for Node-2 as follows:
path = [[10], [11], [5, 21], [5, 22], [5, 23]]
How can I correct my recursive function?
Here's two methods that would accomplish this goal. I'm not quite sure how to fix your structure; it seemed easier to start from scratch.
def get_c_path(self, node):
branches = [[c] for c in node.children]
expanded = self.expand_branches(branches)
while branches != expanded:
branches = expanded
expanded = self.expand_branches(expanded)
return expanded
def expand_branches(self, branches):
new_branches = []
for branch in branches:
last_node = branch[-1]
if last_node.children:
for child in last_node.children:
new_branches.append(branch + [child])
else:
new_branches.append(branch)
return new_branches

Trees in Python

Please help me to understand trees in Python. This is an example of tree implementation I found in the Internet.
from collections import deque
class EmptyTree(object):
"""Represents an empty tree."""
# Supported methods
def isEmpty(self):
return True
def __str__(self):
return ""
def __iter__(self):
"""Iterator for the tree."""
return iter([])
def preorder(self, lyst):
return
def inorder(self, lyst):
return
def postorder(self, lyst):
return
class BinaryTree(object):
"""Represents a nonempty binary tree."""
# Singleton for all empty tree objects
THE_EMPTY_TREE = EmptyTree()
def __init__(self, item):
"""Creates a tree with
the given item at the root."""
self._root = item
self._left = BinaryTree.THE_EMPTY_TREE
self._right = BinaryTree.THE_EMPTY_TREE
def isEmpty(self):
return False
def getRoot(self):
return self._root
def getLeft(self):
return self._left
def getRight(self):
return self._right
def setRoot(self, item):
self._root = item
def setLeft(self, tree):
self._left = tree
def setRight(self, tree):
self._right = tree
def removeLeft(self):
left = self._left
self._left = BinaryTree.THE_EMPTY_TREE
return left
def removeRight(self):
right = self._right
self._right = BinaryTree.THE_EMPTY_TREE
return right
def __str__(self):
"""Returns a string representation of the tree
rotated 90 degrees to the left."""
def strHelper(tree, level):
result = ""
if not tree.isEmpty():
result += strHelper(tree.getRight(), level + 1)
result += " " * level
result += str(tree.getRoot()) + "\n"
result += strHelper(tree.getLeft(), level + 1)
return result
return strHelper(self, 0)
def __iter__(self):
"""Iterator for the tree."""
lyst = []
self.inorder(lyst)
return iter(lyst)
def preorder(self, lyst):
"""Adds items to lyst during
a preorder traversal."""
lyst.append(self.getRoot())
self.getLeft().preorder(lyst)
self.getRight().preorder(lyst)
def inorder(self, lyst):
"""Adds items to lyst during
an inorder traversal."""
self.getLeft().inorder(lyst)
lyst.append(self.getRoot())
self.getRight().inorder(lyst)
def postorder(self, lyst):
"""Adds items to lystduring
a postorder traversal."""
self.getLeft().postorder(lyst)
self.getRight().postorder(lyst)
lyst.append(self.getRoot())
def levelorder(self, lyst):
"""Adds items to lyst during
a levelorder traversal."""
# levelsQueue = LinkedQueue()
levelsQueue = deque ([])
levelsQueue.append(self)
while levelsQueue != deque():
node = levelsQueue.popleft()
lyst.append(node.getRoot())
left = node.getLeft()
right = node.getRight()
if not left.isEmpty():
levelsQueue.append(left)
if not right.isEmpty():
levelsQueue.append(right)
This is programm that makes the small tree.
"""
File: testbinarytree.py
Builds a full binary tree with 7 nodes.
"""
from binarytree import BinaryTree
lst = ["5", "+", "2"]
for i in range(len(lst)):
b = BinaryTree(lst[0])
d = BinaryTree(lst[1])
f = BinaryTree(lst[2])
# Build the tree from the bottom up, where
# d is the root node of the entire tree
d.setLeft(b)
d.setRight(f)
def size(tree):
if tree.isEmpty():
return 0
else:
return 1 + size(tree.getLeft()) + size(tree.getRight())
def frontier(tree):
"""Returns a list containing the leaf nodes
of tree."""
if tree.isEmpty():
return []
elif tree.getLeft().isEmpty() and tree.getRight().isEmpty():
return [tree.getRoot()]
else:
return frontier(tree.getLeft()) + frontier(tree.getRight())
print ("Size:", size(d))
print ("String:")
print (d)
How can I make a class that will count the value of the expression, such that the answer = 7 (5+2). I really want to understand the concept with a small example.
It sounds like your problem isn't trees, which are a much more general (and simple) concept, but in how to properly populate and/or evaluate an expression tree.
If you have your operators specified in post-fix order, it becomes a lot easier.
See this wikipedia article on how to deal with infix notation when parsing input to a desktop calculator. It is called the shunting-yard algorithm.
You should do function that walks a tree in depth first order, calculating value of each node, either just taking value of it (if it is "5" for example), or making calculation (if it is "+" for example) - by walking the tree in depth first order you are sure that all subnodes of given node will be calculated when you are calculating that node (for example "5" and "2" will be calculated when you are calculating "+").
Then, at the root of the tree you'll get the result of the whole tree.
First of all, I'm not going to give much detail in case this is homework, which it sounds a bit like.
You need a method on your tree class that evaluates the tree. I suppose it'll assume that the "root" value of each tree node is a number (when the node is a leaf, i.e. when it has no children) or the name of an operator (When the node has children).
Your method will be recursive: the value of a tree-node with children is determined by (1) the value of its left subtree, (2) the value of its right subtree, and (3) the operator in its "root".
You'll probably want a table -- maybe stored in a dict -- mapping operator names like "+" to actual functions like operator.add (or, if you prefer, lambda x,y: x+y).

Categories