Inorder Binary Tree Traversal (using Python) - python

I am trying to perform an inorder traversal of a tree. The code itself feels right, except it is not working properly. I have a feeling it has to either do with the if condition, how append works in python, or something perhaps with return. This works correctly if I use print instead of return, I think, but I want to be able to use return and still get the correct answer. For example, for the tree [1,None,2,3], my code returns [1] which is clearly incorrect.
Additionally is it possible to solve this problem using list comprehension? If so, any sample code would be greatly appreciated.
Here is my code:
class Solution(object):
def inorderTraversal(self, root):
res = []
if root:
self.inorderTraversal(root.left)
res.append(root.val)
self.inorderTraversal(root.right)
return res
Also before marking this as a duplicate, I know in order traversals have been asked on Stackoverflow (plenty of times), but none of them helped me understand why my understanding is wrong. I would be so grateful if someone helped me learn how to correct my approach versus simply posting another link without explanation. Thank you so much!

The reason this doesn't work is that res only has the value of the first node you give it appended to it; each time you recursively recall the function, it just makes a new res. It is a simple fix though, as follows:
class Solution(object):
def inorderTraversal(self, root):
res = []
if root:
res = self.inorderTraversal(root.left)
res.append(root.val)
res = res + self.inorderTraversal(root.right)
return res
In this, it returns the left branch, the value, and then the right. This can be done much more briefly as follows:
class Solution(object):
def inorderTraversal(self, root):
return (self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)) if root else []

Use this instead , a simple recursion ::
class Node:
def __init__(self,key):
self.left = None
self.right = None
self.val = key
def printInorder(root):
if root:
printInorder(root.left)
print(root.val)
printInorder(root.right)
def printPostorder(root):
if root:
printPostorder(root.left)
printPostorder(root.right)
print(root.val)
def printPreorder(root):
if root:
print(root.val)
printPreorder(root.left)
printPreorder(root.right)
# Driver code
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
print "Preorder traversal of binary tree is"
printPreorder(root)
print "\nInorder traversal of binary tree is"
printInorder(root)
print "\nPostorder traversal of binary tree is"
printPostorder(root)
Source :: here

#Benedict Randall Shaw's answer is already perfect. I just want to add some fun to it in a pythonic way. Although the doc does not suggest using a mutable object as default parameter, this will somewhat simplify the code by treating the default mutable list as a class member of the python function.
The difference is only the += is replaced by =, since the res is always the same list object inside the function before the function object is garbage collected.
def inorderTraversal(root, res=[]):
if root:
res = inorderTraversal(root.left)
res.append(root.val)
res = inorderTraversal(root.right)
return res

Yet another approach to output a list, the advantage being that you need to add values only to a single list:
def inorder(root):
return_list = []
def innerInOrder(root):
if root == None:
return
innnerInOrder(root.left)
return_list.append(root.data)
innerInOrder(root.right)
innerInOrder(root)
return return_list

You could just declare the list outside the function so that it does not create a new list everytime you call the function ( since it's a recursive function), but you could use other approaches posted. :-)

Related

Calling a linked list

I'm new to programming, so excuse the possibly stupid question.
I'm doing leetcodes and I got to the linked lists. I think I understand them okay, it's just that I don't know how to test my code/call my function(?)
Problem I'm working on
Here's my code, I know it works since I uploaded it onto leetcode, but I would still like to be able to run it on my machine.
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
I guess I have two different problems:
the "Optional[ListNode]) -> Optional[ListNode]:" part
and the actual calling of the function
Some questions before used the "typing" module functions like "List", so I would simply import them and they wouldn't be a problem. But I'm not really sure what to do here
To check my solutions, I write a short piece of code that I can put example inputs into
Solution = Solution()
print(Solution.middleNode(head = [1,2,3,4,5,6]))
But isn't the "head" there, just a normal list? Do I have to create an extra function separately to create the "links". I've seen the creation of a linked list done by calling a function every time you want to add a new node. So would I use a for loop to add my example case?
well if you looking for internal boilerplate, below is code for that.
here you need to create classes for nodes, linked list and solutions,.
then with the given number, you need to create a linkedlist object.
this above part is done in leetcode by themself and this object is passed to class Solution method middleNode, where OP code run and give result. next once output is got it is compared with existing solution
# Node class for individual nodes
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
# linked list class, to create a linked list of the list nodes
class LinkedList:
def __init__(self):
self.head = None
# adding a node element to linked list
def add(self, node):
if self.head is None:
self.head = node
else:
curr = self.head
while curr.next:
curr = curr.next
curr.next = node
curr = node
# printing element of existing linked list
def print_ll(self):
curr= self.head
while curr:
print(curr.val)
curr= curr.next
# leetcode solution class
class Solution:
def middleNode(self, head) :
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
# value with which we create list nodes
values = [1,2,3,4,5,6,7,8,9,10]
ll = LinkedList() # create a linked list class object
for i in values:
node = ListNode(i) # creating a list node
ll.add(node) # adding list node to linked list
#ll.print_ll() # printing linked list
x = Solution().middleNode(ll.head) # passing linked list object to leetcode solution method and getting result
while x: # printing result
print(x.val)
x=x.next
I think the problem on LeetCode is poorly worded. head = [1,2,3,4,5] is not really a head as it should only refer to the first item in the list - there seems to be a bit of hidden boilerplate code that creates a linked list from input list and an output list from output node.
Here's an example code that works similiar to the LeetCode task.
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
inp = [1,2,3,4,5,6]
next = None
for i in reversed(inp):
next = ListNode(i, next) # next points to head at the end of the loop
res = Solution().middleNode(next)
out = []
while res:
out.append(res)
res = res.next
print([o.val for o in out])
to make your code work on your machine you have to implement a couple of things:
First, for your first answer, you have to implement the class ListNode given at the top of the leetcode-page:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
The you import "Optional" from typing:
from typing import Optional
Then you have the prerequisites for your code.
You have to initialise the class, as you have mentioned. The only problem here is, that your variable has the same name as your class, what could cause trouble later.
To finish, you have to call your function as you already did, with one little difference: This function has to be called with "head" as a variable of type ListNode, not List, and gives you back a variable of the type ListNode.
In a nutshell, this would be my solution (of course you can and as much ListNodes as you want):
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
# Initialise class
s = Solution()
# Defining nodes of the list, assigning always the next node.
seven = ListNode(7)
six = ListNode(6, next=seven)
five = ListNode(5, next=six)
four = ListNode(4, next=five)
three = ListNode(3, next=four)
two = ListNode(2, next=three)
one = ListNode(1, next=two)
# Calling your function (with "one" as your head node of the list)
# NOTE: As this gives you back an attribute of type ListNode, you have to access the "val" attribute of it to print out the value.
print(s.middleNode(one).val)

Python variable value assignment in recursion

There are two solution for a problem:
Problem is :
Enter the root node of a binary tree and an integer to print out the path where the sum of the node values in the binary tree is the input integer. A path is defined as a path from the root node of the tree to the next node until the leaf node passes. (Note: In the list of return values, the array with the largest array length is ahead)
solution one
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def FindPath(self, root, expectNumber):
if not root:
return []
result=[]
path=[root]
path_sum=0
def find(root,path,path_sum):
isleaf= root.left==None and root.right==None # a bool,whether is leaf node
path_sum+=root.val
if isleaf and path_sum==expectNumber:
t=[]
for i in path:
t.append(i.val)
result.append(t) # add a appropriate path's value to result
if path_sum<expectNumber:
if root.left:
find(root.left,path+[root.left],path_sum)#note!!!!!
if root.right:
find(root.right,path+[root.right],path_sum)#note!!!!!
find(root,path,path_sum)
return result
solution 2
class Solution:
def FindPath(self, root, expectNumber):
if not root:
return []
result=[]
path=[]
path_sum=0
def find(root,path,path_sum):
isleaf= root.left==None and root.right==None
path.append(root)#note!!!!!
path_sum+=root.val
if isleaf and path_sum==expectNumber:
t=[]
for i in path:
t.append(i.val)
result.append(t)
if path_sum<expectNumber:
if root.left:
find(root.left,path,path_sum)
if root.right:
find(root.right,path,path_sum)
path.pop()#note!!!!!
find(root,path,path_sum)
return result
I don't know why in solution 1 the path list don't need pop operation but solution 2 need. In other word why solution 1 don't share a path list, but solution 2 does.
Please help me, I cann't find such paper figure me out!
My point is not about class , you can use function to solve this problem too.
What I care is Python variable value assignment in recursion!!!
I find your code has a lot of mistakes that will make it hard to trace:
**** First: any def or function inside any Python class should be lower case with underscores, so we can figure out what is class from a function, so your FindPath() should be >>>>>> find_path()
**** Second: If you wand to declare any arguments to a the global scope of a class, you should do that inside a function as a constructor or initializer, so your code for an E.G should be :
class Solution:
def __init__(self, root, expect_number):
self.root = root
self.expect_number = expect_number
and any time you will call any argument inside the class, you should call it with the (self.arg), e.g self.root
**** Third: this line is not understandable at all :
def find(root,path,path_sum):
isleaf= root.left==None and root.right==None
this is totally wrong you are assigning a None value to preassaigned value to isleaf, and you again give the isleaf variable an (and) word so, as a logical or pythonic logic : how would the isleaf will understand to get the two values (root.left and root.right) which are getting a None values, does not make any sense.
so please give us an idea about what exactly do you want to do here.
**** Fourth: consider to give one space after and before any operator so instead of
"if path_sum
**** Don't afraid to give the variables or arguments a real names to discripe the real needs for it, or at least try to give a comment for it, So e.g : what is t = [] is doing!!!!!!!
So please try to be more specific so you can find good help for your problems, and to make your code more pythonic.
New Edit:
In solution no 2 : every time you call the find() function, you are appending or adding the 'root' value to the path list
def find(root,path,path_sum):
isleaf= root.left==None and root.right==None
path.append(root) # here you added the root to the path
and the code still recursive till this condition is false:
if path_sum<expectNumber:
and when it false, it will start to call the pop() method, which will remove
the last 'root', added to the path list:
path.pop()
and then it calls the next line, which will call the find function again
find(root,path,path_sum)
but this time will call it with empty path value, WHY?
because the first path list object "path=[]" is at the same level scope as
the calling of the last find function "find(root,path,path_sum)"
so the inner path argument and it's values not seen by the outer path scope, they only seen by the find() function it self.
And this scope issues exactly the same to "Solution 1", except you are passing a path list with root value, and when this condition is False
if path_sum<expectNumber:
the code will call the find() function again but with path only having the root value in the first announcement "path=[root]".
And After all I think with respect you are not sharing the whole code for privacy issue, so it's hard to find the answer easily.
You can simplify your recursive method several ways. First, at each iteration, check if the value of the node passed to the method along with the sum of the current path contents is less than or equal to the desired value. Second, should the latter be smaller, call the method on the left and right sides of the tree:
class Solution:
#classmethod
def find_path(cls, head, val:int, current = []):
if sum(current) == val:
yield current
elif head.value+sum(current) < val:
if head.left is not None:
yield from cls.find_path(head.left, val, current+[head.value])
if head.right is not None:
yield from cls.find_path(head.right, val, current+[head.value])
elif head.value+sum(current) == val:
yield current+[head.value]
Tree class for demonstration:
class Tree:
def __init__(self, **kwargs):
self.__dict__ = {i:kwargs.get(i) for i in ['left', 'right', 'value']}
t = Tree(value=10, left=Tree(value=8, left=Tree(value=3), right=Tree(value=5)), right=Tree(value=2, left=Tree(value=2)))
"""
10
/ \
8 2
/ \ /
3 5 2
"""
results = [list(Solution.find_path(t, i)) for i in [12, 14, 23]]
Output:
[[[10, 2]], [[10, 2, 2]], [[10, 8, 5]]]

what's difference between these two statements about passing variables in Python recursively

I'm a new python learner. and there is a question confusing me a lot cause it really waste much time to think about.
There is a algorithm puzzle about binary tree, and a sum, you should find all root-to-leaf paths where each path's sum equals the given sum.
For example:
Given the below binary tree and sum = 22
An example picture here
I have written a python recursive method like blew and it runs correctly on online judgment.
#definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val=x
self.left=None
self.right=None
class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
res=[]
if not root:
return res
temp=[root.val]
self.helper(root,sum,res,temp)
return res
def helper(self, root, sum, res, temp):
if not root:
return 0
if root.left==None and root.right==None and sum==root.val:
res.append(temp)
if root.left!=None:
self.helper(root.left,sum-root.val,res,temp+[root.left.val])
if root.right!=None:
self.helper(root.right,sum-root.val,res,temp+[root.right.val])
in the last four lines, I invoke the helper function recursively to find the path sum by pass root left child and root right child.
However, if i rewrite the code like below, I mean only last four lines
if root.left!=None:
temp+=[root.left.val]
self.helper(root.left,sum-root.val,res,temp)
if root.right!=None:
temp+=[root.right.val]
self.helper(root.right,sum-root.val,res,temp)
it gives me wrong answer and can't pass the online judgment.
Dose anyone know what is the difference between this two kind of ways in pass the parameter to a function in python. or it's any declare and pass problem in my code.
In my view, I can't see any difference. Thanks everyone.help me !
+= alters a list in-place:
>>> def inplace(l):
... l += ['spam']
...
>>> def new_list(l):
... l = l + ['spam']
...
>>> a = ['foo']
>>> inplace(a)
>>> a
['foo', 'spam']
>>> a = ['foo']
>>> new_list(a)
>>> a
['foo']
Your original code passes in a new list each time:
self.helper(root.left,sum-root.val,res,temp+[root.left.val])
but your altered code shares temp across all recursive calls and extends it each time. This matters because by creating a new list you gave the recursive calls for the left branch a new, independent list from the right branch of your recursion. By extending the list with += you now give a larger list to the right branch after processing the left branch.
When you say temp += ... you are modifying temp. But you use it in both the left and right cases.
So you have:
temp = [0]
if root.left is not None:
temp += [1] # Now temp is [0, 1], probably okay
...
if root.right is not None:
temp += [2] # Now temp is [0, 1, 2], not [0, 2]!
The second version is incorrect because you would be updating the temp variable between the left leaf check and the right leaf check
if root.left!=None:
temp+=[root.left.val] # temp updated here
self.helper(root.left,sum-root.val,res,temp)
if root.right!=None:
temp+=[root.right.val] # the updated value could be used here, which is wrong
self.helper(root.right,sum-root.val,res,temp)

python returning a list from a recursive method

Im using a binary tree described in this book
problem solving with algorithms and data structures
class BinaryTree:
def __init__(self,rootObj):
self.key = rootObj
self.leftChild = None
self.rightChild = None
There is already a preorder traversal method defined as follows.
def preorder(tree):
if tree:
print(tree.self.key)
preorder(tree.getLeftChild())
preorder(tree.getRightChild())
I just want to add a return value of the list of nodes visited. So I can do something like
for i in preorder(tree):
etc...
Im having trouble returning a list from a recursive method. The recursion stops as soon as it hits the 'return' I've tried variations using
return [tree.self.key] + preorder()
Or
yield ...
Any ideas?
Are you sure you want tree.self.key and not simply tree.key when you print?
Otherwise, a solution with yield from (Python 3.3+):
def preorder(tree):
if tree:
yield tree
yield from preorder(tree.getLeftChild())
yield from preorder(tree.getRightChild())
Or with simple yield:
def preorder(tree):
if tree:
yield tree
for e in preorder(tree.getLeftChild()):
yield e
for e in preorder(tree.getRightChild()):
yield e
Note that using yield or yield from transforms the function into a generator function; in particular, if you want an actual list (for indexing, slicing, or displaying for instance), you'll need to explicitly create it: list(preorder(tree)).
If you have a varying number of children, it's easy to adapt:
def preorder(tree):
if tree:
yield tree
for child in tree.children:
yield from preorder(child)
You have to actually return a value from the recursive function (currently, it's just printing values). And you should build the list as you go, and maybe clean the code up a bit - something like this:
def preorder(tree):
if not tree:
return []
# optionally, you can print the key in this line: print(self.key)
return [tree.key] + preorder(tree.leftChild) + preorder(tree.rightChild)
You can add second argument to preorder function, something like
def preorder(tree, visnodes):
if tree:
visnodes.append(tree.self.key)
print(tree.self.key)
preorder(tree.getLeftChild(), visnodes)
preorder(tree.getRightChild(), visnodes)
...
vn = []
preorder(tree, vn)
You can simply return a concatenated list for each recursive call, which combines the current key, the left subtree and the right subtree:
def preorder(tree):
if tree:
return ([tree.key] + preorder(tree.getLeftChild()) +
preorder(tree.getRightChild()))
return []
For an n-ary tree:
def preorder(tree):
if tree:
lst = [tree.key]
for child in tree.children:
lst.extend(preorder(child))
return lst
return []

How to traverse Linked-Lists Python

I am trying to figure out how I can traverse linked list in Python using Recursion.
I know how to traverse linked-lists using common loops such as:
item_cur = my_linked_list.first
while item_cur is not None:
print(item_cur.item)
item_cur = item_cur.next
I was wondering how I could turn this loop into a recursive step.
Thanks
You could do something like this:
def print_linked_list(item):
# base case
if item == None:
return
# lets print the current node
print(item.item)
# print the next nodes
print_linked_list(item.next)
It looks like your linked list has two kinds of parts. You have list nodes, with next and item attributes, and a wrapper object which has an attribute pointing to a the first node. To recursively print the list, you'll want to have two functions, one to handle the wrapper and a helper function to do the recursive processing of the nodes.
def print_list(linked_list): # Non-recursive outer function. You might want
_print_list_helper(linked_list.first) # to update it to handle empty lists nicely!
def _print_list_helper(node): # Recursive helper function, gets passed a
if node is not None: # "node", rather than the list wrapper object.
print(node.item)
_print_list_helper(node.next) # Base case, when None is passed, does nothing
Try this.
class Node:
def __init__(self,val,nxt):
self.val = val
self.nxt = nxt
def reverse(node):
if not node.nxt:
print node.val
return
reverse(node.nxt)
print node.val
n0 = Node(4,None)
n1 = Node(3,n0)
n2 = Node(2,n1)
n3 = Node(1,n2)
reverse(n3)

Categories

Resources