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)
Related
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]]]
0
/ \
1 2
/ \ /|\
3 4 5 6 7
I'm trying to return the nodes without children (3,4,5,6,7) from an object using a recursive function.
It works using a global variable and this function:
def find(self, nodes):
if not hasattr(self, 'children'):
nodes.append(self)
else:
for i in self.children:
i.find(nodes)
nodes = []
node.find(nodes) # can be any node (0,1,2,3,4, etc.)
print(nodes)
But I would like to use return in my function. I tried something like this:
def find2(self):
if not hasattr(self, 'children'):
return self
else:
for i in self.children:
return i.find2()
nodes = root.find2()
print(nodes)
But I get only 1 node. I also tried passing an array like on this post: PYTHON Return a list from a recursive function. But I don't get the result I want because tree structure (I guess)...
I'm stuck, can you help me? How to "return the result for each iteration of the recursive function to a variable"? Thank you
This is the input example:
0
/ \
1 2
/ \ /|\
3 4 5 6 7
Think about what you want the (recursive) function to return for each of the nodes:
when called on the root (0), it should return the full result (3, 4, 5, 6, 7)
when called on a leaf node (e.g. 5), it should return that node (5)
for any other node (e.g. 1), it does as if that was a root node of a smaller tree
So, it sometimes returns one result and sometimes many.
The error in your code is here, because the function ends on the first return, it does not return many:
for i in self.children:
return i.find2()
There are two solutions:
make a generator function, or
make a function which returns a list (make it return a list always, even if it has just one element!)
So, option 1:
def find(self):
if not hasattr(self, 'children'):
yield self
else:
for child in self.children:
yield from child.find()
option 2:
def find(self):
if not hasattr(self, 'children'):
return [self]
else:
rtn = []
for child in self.children:
for result in child.find():
rtn.append(result)
return rtn
I prefer the generator. Additionally, I don't particularly like the fact that some of your nodes have a children attribute, while others do not. I would make sure all of them had children, which could be empty or non-empty. Then, the code becomes:
def find_leaves(self):
if self.children:
for child in self.children:
yield from child.find_leaves()
else:
yield self
Note that in your base case, you return one node. That node then get propagated back in the recursion, and eventually returned. I.e. the node you are returned is the first one without children you hit. There are multiple ways to fix this issue (e.g. by returning and concatenating lists), but I think a natural way to do this is to make your function a generator. To do this, simply replace the return by a yield. Then, the return value of the function functions as an iterator, with each iteration yielding the next value that would be "returned" in execution until the function terminates.
You've not provided enough code for me to make a runnable and testable example but here's my guess of what you seek:
def find(self):
if not hasattr(self, 'children'):
return [self]
nodes = []
for child in self.children:
return nodes.extend(child.find())
return nodes
# ...
nodes = root.find()
print(nodes)
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. :-)
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 []
I've created a general tree in python, by creating a Node object. Each node can have either 0, 1, or 2 trees.
I'm trying to create a method to print a list of all the nodes in a tree. The list need not be in order. Here's my simplistic attempt:
def allChildren(self, l = list()):
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
The first time I run this method, it works correctly. However, for some reason it is storing the previous runs. The second time I run the method, it prints all the nodes twice. Even if I create 2 separate trees, it still remembers the previous runs. E.g: I create 2 trees, a and b. If I run a.allChildren() I receive the correct result. Then I run b.allChildren() and recieve all of a's nodes and all of b's nodes.
You have a mutable value as the default value of your function parameter l. In Python, this means that when you call l.append(self), you are permanently modifying the default parameter.
In order to avoid this problem, set l to a new list every time the function is called, if no list is passed in:
def allChildren(self, l = None):
if l is None:
l = list()
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
This phenomenon is explained much more thoroughly in this question.
try this:
def allChildren(self, l = None):
if(l==None):
l = list()
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
And check out this answer for explanation.
If you're writing default parameter like l = list(), it will create list when compiling function, so it will one instance of list for all function calls. To prevent this, use None and create new list inside the function:
def allChildren(self, l = None):
if not l: l = []
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l