I am trying this coding problem on leetcode and not able to debug the error!!
It's been 3 hours and I tried re-writing the logic again but I am still missing something. What else can I add to make it work against the test case:
>>>input - [1,2,3,4,null,null,5]
>>>expected output - [[4,5],[2,3],[1]]
Although this code is working for the given test case:
>>> input - [3,9,20,null,null,15,7]
>>> output - [[15,7],[9,20],[3]]
This is my effort:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
queue = []
level = []
result = []
if root is None:
return None
result.append([root.val])
queue.append(root)
while len(queue) > 0:
a = queue[0]
ans = self.traverse_value(a.left, a.right, queue)
if ans is not None:
result.append(ans)
queue.pop(0)
return reversed(result)
def traverse_value(self, r_left, r_right, queue):
if r_left is None and r_right is None: # both l and r are none
return
elif r_left is None and r_right is not None: # right is not none
queue.append(r_right)
return [r_right.val]
elif r_left is not None and r_right is None: # left is not none
queue.append(r_left)
return [r_left.val]
elif r_left is not None and r_right is not None: # both are not none
queue.append(r_left)
queue.append(r_right)
return [r_left.val, r_right.val]
Your code can only create sublists of up to two elements, via the function traverse_value. This cannot be right, since obviously more wide trees will have more elements on the same level. Your algorithm has no provision to put "cousins" in the same list, only direct siblings.
Your BFS approach is certainly a good idea, but make sure to distinguish correctly between layers, so you know when to put values in the same list or in a new one:
result = []
if root is None:
return None
queue = [root]
while len(queue):
# get the values out of the current queue
result.append([a.val for a in queue])
# perform a separate loop for the this layer only
nextlayer = []
for a in queue:
# just extend this new list for the whole layer
if a.left:
nextlayer.append(a.left)
if a.right:
nextlayer.append(a.right)
# finally put that whole layer in the queue
queue = nextlayer
return reversed(result)
For your info, it can also be done with a DFS solution where you just keep track of the depth you are at, and use that as index in the solution list:
level = []
def recur(node, depth):
if not node:
return
if depth >= len(level):
level.append([])
level[depth].append(node.val)
recur(node.left, depth+1)
recur(node.right, depth+1)
recur(root, 0)
level.reverse()
return level
Related
I am trying to write a BFS algorithm for a Binary Search Tree using Python3.
I first initialised the class, defined an insert method, and inserted some random numbers:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def insert(self, data):
if data <= self.data:
if self.left == None:
self.left = Node(data)
else:
self.left.insert(data)
else:
if self.right == None:
self.right = Node(data)
else:
self.right.insert(data)
root = Node(1)
root.insert(0)
root.insert(2)
root.insert(1.5)
root.insert(2.4)
root.insert(1.6)
root.insert(2.3)
Then, I tried to write a recursive BFS method:
def inLineTraversal(self, queue=[]):
if queue == []: # Base condition
return
temp = queue
for node in temp:
print(node.data)
if node.left != None:
queue.append(node.left)
if node.right != None:
queue.append(node.right)
queue.pop(0)
self.inLineTraversal(queue)
However, this produced 1,2,2.4,1.5,2.3,2.3,1.6 as opposed to the correct result of 1,0,2,1.5,2.4,1.6,2.3.
I later used a while loop to perform the BFS, which correctly produced 1,0,2,1.5,2.4,1.6,2.3:
def inLineTraversal(self):
queue = [self]
while queue != []:
s = queue.pop(0)
print(s.data)
if s.left != None:
queue.append(s.left)
if s.right != None:
queue.append(s.right)
What was wrong with the recursive solution?
The problem is in this line:
temp = queue
This doesn't create a new copy of queue, as you probably expected, it just gives it an additional name temp - but both names refer to the same list.
So, further on, you iterate on this list while modifying it, which almost always leads to problems.
Just create a copy of your list, like :
temp = queue[:]
And everything works fine
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def insert(self, data):
if data <= self.data:
if self.left == None:
self.left = Node(data)
else:
self.left.insert(data)
else:
if self.right == None:
self.right = Node(data)
else:
self.right.insert(data)
def inLineTraversalRecursive(self, queue=[]):
if queue == []: # Base condition
return
temp = queue[:]
for node in temp:
print(node.data)
if node.left != None:
queue.append(node.left)
if node.right != None:
queue.append(node.right)
queue.pop(0)
self.inLineTraversal(queue)
def inLineTraversalLoop(self):
queue = [self]
while queue != []:
s = queue.pop(0)
print(s.data)
if s.left != None:
queue.append(s.left)
if s.right != None:
queue.append(s.right)
root = Node(1)
root.insert(0)
root.insert(2)
root.insert(1.5)
root.insert(2.4)
root.insert(1.6)
root.insert(2.3)
root.inLineTraversalLoop()
print()
root.inLineTraversalRecursive([root])
Output:
1
0
2
1.5
2.4
1.6
2.3
1
0
2
1.5
2.4
1.6
2.3
This is because you put self.inLineTraversal(queue) outside the for loop. Also this line temp = queue is redundant.
So the correct code for your recursive inLineTraversal would be:
def inLineTraversal(self, queue=[]):
if queue == []: # Base condition
return
for node in queue:
print(node.data)
if node.left != None:
queue.append(node.left)
if node.right != None:
queue.append(node.right)
queue.pop(0)
self.inLineTraversal(queue) # inside of the for loop
I tested and ran this modified method, I got the result you expected: 1,0,2,1.5,2.4,1.6,2.3.
I can see 2 problems in your code
1.) In the InlineTraversal method, You are copying queue to temp array which is not the correct way for copying elements. You are doing shallow copy here. That means both the lists(Queue and Temp) will point to element in same memory location.
2.) You are removing the elements from list inside for loop. you are iterating over Temp list and removing element from queue list which are actually same lists. So, basically you are removing element from same list on which you are iterating which is not a good practice.
To Fix this, perform deep copy on queue list by using
temp = queue[:]
I'm just getting started with binary trees and I have this task where I have to do a preorder iterative traversal search for a given binary tree '[1,null,2,3]'.
I tried to use a new binarytree module that I found, but it didn't worked and I saw a youtube video where some guy did it recursively but I just can't figure out.
#Input = [1,null, 2,3]
# 1
# \
# 2
# /
# 3
#Expected output = [1,2,3]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
I'm just clueless, I wrote an algorithm but I can't turn it into actual functional code. Also I don't understand how the root: TreeNode works. Does it turn every element of the list into a TreeNode object? So far my best try had been this and it's obviously wrong in many ways.
def preorderTraversal(self, root: TreeNode) -> List[int]:
result = []
for i in root:
if i =! root[0] and root.left =! None:
root.left = i
if root.left =! null:
root.left.left = i
elif root.left == null:
root.right.left = i
elif root.left
result.append(i)
elif root.right == None:
root.right = i
else:
continue
A few points:
Function preorderTraversal should have no self parameter; it is not a method of a class.
I have modified the TreeNode class to make it more convenient to specify its children TreeNode objects.
Function preorderTraversal takes as an argument a TreeNode object. As I mentioned in a comment, your statement, #Input = [1,null, 2,3], is difficult to make sense of.
You need to keep a last in/first out (LIFO) stack of unvisited TreeNode objects to implement an iterative (rather than recursive solution). In the code below, variable nodes serves that purpose.
The code:
from typing import List
class TreeNode:
def __init__(self, val, left=None, right=None):
self.x = val
self.left = left
self.right = right
n3 = TreeNode(3)
n2 = TreeNode(2, left=n3)
n1 = TreeNode(1, right=n2)
def preorderTraversal(root: TreeNode) -> List[int]:
result = []
nodes = []
nodes.append(root) # initial node to visit
while len(nodes): # any nodes left top visit?
node = nodes.pop() # get topmost element, which is the next node to visit
result.append(node.x) # "output" its value before children are visited
if node.right is not None:
# show this node must be visited
nodes.append(node.right) # push first so it is popped after node.left
if node.left is not None:
# show this node must be visited
nodes.append(node.left)
return result
print(preorderTraversal(n1))
Prints:
[1, 2, 3]
Or a more complicated tree:
10
/ \
8 2
/ \ /
3 5 2
n3 = TreeNode(3)
n5 = TreeNode(5)
n8 = TreeNode(8, left=n3, right=n5)
n2a = TreeNode(2)
n2b = TreeNode(2, left=n2a)
n10 = TreeNode(10, left=n8, right=n2b)
print(preorderTraversal(n10))
Prints:
[10, 8, 3, 5, 2, 2]
You can use the queue data structure for it.
queue = []
result = []
queue.append(root)
while queue:
node = queue.pop()
result.append(node.val)
if node.left is not None:
queue.insert(0, node.left)
if node.right is not None:
queue.insert(0, node.right)
return result
This is a problem from leetcode platform, here is my solution. Runtime: 28 ms, faster than 81.08% of Python3 online submissions for Binary Tree Preorder Traversal.
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
return [root.val] + self.preorderTraversal(root.left) + self.preorderTraversal(root.right)
I am doing a Python program that implements linked list to support a few functions, one of the functions I need to do is to reverse a stack. I have made a Node, LinkedList and Stack classes, here is my Code so far:
class ListNode:
def __init__(self, Object):
self.Object = Object
self.next = None
class LinkedList:
def __init__(self):
self.head = None # first node
self.tail = None # last node
def addLast(self, Object):
newNode = ListNode(Object)
if self.head == None:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
self.tail = newNode
def removeFirst(self):
if self.head == None:
return
self.head = self.head.next
if self.head == None:
self.tail = None
def removeLast(self, Object):
if self.head == None:
return
current = self.head
prev = None
while current.next != None:
prev = current
current = current.next
if prev == None:
self.head = None
self.tail = None
else:
prev.next = None
self.tail = prev
def get(self, index):
current = self.head
i = 0
while i < index and current != None:
current = current.next
i = i + 1
if current != None and index >= 0:
return current.Object
else:
return None
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.next
return count
def isEmpty(self):
return self.head == None
def printList(self):
if self.head != None:
current = self.head
while current != None:
print(current.Object, end = ' ')
current = current.next
print()
# -------------------- STACK ---------------------------------------------------
class Stack:
# constructor implementation
def __init__(self):
self.llist = LinkedList()
def front(self):
return self.llist.get(0)
def dequeue(self):
self.llist.removeFirst()
def queue(self, Object):
self.llist(Object)
def push(self, Object):
self.llist.addLast(Object)
def pop(self, Object):
self.llist.removeLast(Object)
def printStack(self):
self.llist.printList()
def size(self):
return self.llist.size()
def isEmpty(self):
return self.llist.isEmpty()
# ----------------------- Reverse LIST ------------------------------
def Reverse(S):
# S is a Stack Object
Here is my attempt at the problem:
def rRecursive( self ) :
self._rRecursive( self.head )
def _reverseRecursive( self, n ) :
if None != n:
right = n.next
if self.head != n:
n.next = self.head
self.head = n
else:
n.next = None
self._rRecursive( right )
def Reverse(S):
s.rRecursive()
If this was an ordinary list I could easily reverse it using [::-1] but I cannot since the linkedlist is an object. I was thinking maybe I could use temporary values so I can someone append the beginning of the stack to a list and then somehow convert it back into a stack object.
Edit for duplication: The goal of my program is use an existing Stack and reverse it. The linked post deals with a linked list that was already in a list format.
def get(self, index):
current = self.head
i = 0
while i < index and current != None:
current = current.next
i = i + 1
if current != None and index >= 0:
return current.Object
else:
return None
Edit 2: added my get function.
class Stack:
# constructor implementation
def __init__(self):
self.llist = LinkedList()
def front(self):
return self.llist.get(0)
# push method implementation
def push(self, Object):
self.llist.addLast(Object)
def pop1(self):
self.llist.removeLast1()
def Reverse(S):
new_stack = Stack()
while not S.isEmpty():
new_stack.push(S.front())
S.pop1()
return new_stack
# Current Stack after Push: 12 14 40 13
# Stack after Pop: 12 14 40
# Stack after Reversal: 12 12 12
Edit 3: Added a rework of my code, it returns back a wrong reversal with the first element over and over again.
It's quite easy to reverse a stack using basic stack operations. Pop each item off the old stack and push it onto a new one.
def reverse(stack):
new_stack = Stack()
while not stack.isEmpty():
new_stack.push(stack.front())
stack.pop()
return new_stack
You could do something similar to destructively reverse the LinkedList within the Stack while reusing the stack object itself, you'd just need to use the list operations rather than the stack operations that are aliased to them.
Speaking of stack operations, you'll probably find that your stack performs better if you push and pop from the front, rather than the back. Removing an item from the end of the linked list requires iterating over the whole list (to find the next-to-last node). In contrast, both adding and removing from the front are fast.
You shouldn't have to fiddle with link pointers in your reversal function. I assume that you have a pop() method and other basics with your stack; if not, then clone your removeFirst function to return the removed node.
Now, the recursive function is simple: pop the head of the list, reverse the remaining stack (if any), and add the popped node to the end. Does this handle your problem?
def reverseStack(self):
move_me = self.pop()
if not self.isEmpty():
return (self.reverseStack()).addLast(move_me)
else:
new_stack = Stack()
return new_stack.addLast(move_me)
Other approaches to solving this problem: Cheat.
Define a __iter__ method (which makes sense in any event; iteration is a core Python behavior) to make your type iterable. Simple example:
def __iter__(self):
cur = self.head
while cur is not None:
yield cur.Object
cur = cur.next
Then just do:
values = list(self) # Creates a list containing the current set of values
self.head = self.tail = None # Clear existing linked list
# Add back all the values in reverse order
for value in reversed(values):
self.addLast(value)
Sure, it's likely less efficient in memory allocation/deallocation overhead than doing it properly. But the effect is likely marginal, and it simplifies the implementation code dramatically.
Of course, doing it properly isn't that hard, it's just slightly more confusing (totally untested, but it should be close to right):
def reverse(self):
# Start at beginning, which will be new end
cur, last = self.head, None
# Reverse head and tail pointers in advance
self.head, self.tail = self.tail, self.head
# Traverse while reversing direction of each node pointer
while cur is not None:
# Tuple pack and unpack allows one-line variable swap
cur.next, cur, last = last, cur.next, cur
The usual algorithm for reversing things using basic data structures is to use the fact that a stack is a first in last out data structure. That means if you pop until the stack is empty, you will get the items in the opposite order you pushed them on.
But it looks like you want to do this via recursive functions rather than an explicit stack - in this case, your function would normally fetch the front element,then recurse on the rest of the data structure, then handle that first element. This gets all the elements off in order, but handles them in the opposite order as each recursive call finishes and you work your way back up the call stack. If you neex to add the elements to a reversed data structure (and not just print them), you can build it up via return values by noticing that once you have the reverse if everything after the current element, you just need to attach that element to the front and you have the reverse of everything you were handed.
class Node(object):
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
def Reverse(head):
if head == None :
return None
elif head.next == None :
return head # returns last element from stack
else :
temp = head.next # stores next element while moving forward
head.next = None # removes the forward link
li = Reverse(temp) # returns the last element
temp.next = head # now do the reverse link here
return li
def main() :
temp4 = Node(4,None)
temp3 = Node(3,temp4)
temp2 = Node(2,temp3)
head = Node(1,temp2)
res = Reverse(head)
while res != None :
print(res.data)
res = res.next
main()
The end goal is to copy a node from one tree to another tree. I want to visit each node in a binary tree and return a node instance after a number of traverses. I cannot seem to figure out how to return a specific node. Every time the node returned matches the id of the root node since I pass the root node to the function.
class node():
def __init__(self):
self.parent = None
self.left = None
self.right = None
def randnode(self, target):
global count
if target == count:
# print 'At target', '.'*25, target
return self
else:
if self.left is not None:
count += 1
self.left.randnode(target)
if self.right is not None:
count += 1
self.right.randnode(target)
If you're doing a DFS and counting iterations, you don't even need recursion, just a stack of places to try, and popping/pushing data.
def dfs(self,target):
count = 0
stack = [start]
while stack:
node = stack.pop()
if count == target:
return node
if node is None: # since we push left/right even if None
continue # stop pushing after we hit None node
stack.extend([self.left,self.right])
return -1 # ran out of nodes before count
Bonus points : swapping stack to a queue for BFS
Apart from that, you might want to pass the count as a parameter, like all self-respecting recursive calls, you can make this stateless ;-)
class node():
def __init__(self):
self.parent = None
self.left = None
self.right = None
def randnode(self, target,count=0):
if target == count:
# print 'At target', '.'*25, target
return self
if self.left is not None:
return self.left.randnode(target,count + 1)
if self.right is not None:
return self.right.randnode(target,count + 1)
I'm trying to make a list of all items in a binary search tree. I understand the recursion but I don't know how to make it return each value and then append it into a list. I want to create a function called makeList() that will return a list of all the items in my tree. All the functions in my programs work except the makeList() function and are included to make sure everyone understands the basic structure of how I set up my tree.
class Node(object):
def __init__(self, data):
self.data = data
self.lChild = None
self.rChild = None
class Tree(object):
def __init__(self):
self.root = None
def __str__(self):
current = self.root
def isEmpty(self):
if self.root == None:
return True
else:
return False
def insert (self, item):
newNode = Node (item)
current = self.root
parent = self.root
if self.root == None:
self.root = newNode
else:
while current != None:
parent = current
if item < current.data:
current = current.lChild
else:
current = current.rChild
if item < parent.data:
parent.lChild = newNode
else:
parent.rChild = newNode
def inOrder(self, aNode):
if aNode == None:
pass
if aNode != None:
self.inOrder(aNode.lChild)
print aNode.data
self.inOrder(aNode.rChild)
def makeList(self, aNode):
a = []
self.inOrder(aNode)
a += [aNode.data]
print a
n = Tree()
for i in [4,7,2,9,1]:
n.insert(i)
n.makeList(n.root)
Looking at my makeList() function I can see why it doesn't work but I don't know how to make it work.
EDIT
Ok, I got it! And I even got two answers which are:
def makeList(self, aNode, a = []):
if aNode != None:
self.makeList(aNode.lChild, a)
a += [aNode.data]
self.makeList(aNode.rChild, a)
return a
and
def makeList2(self, aNode):
if aNode is None:
return []
return self.makeList2(aNode.lChild) + [aNode.data] + self.makeList2(aNode.rChild)
And looking back I can see that I do not understand recursion very well so it's time to hit the books! Anyone have any good resources on recursion?
Another question, so say I call my makeList() function. When Python goes through makeList(), when it gets to the self.makeList(aNode.lChild, a) does it begin running the function again while it's still finishing up the makeList() function or does everything stop and it just starts over with it's new aNode?
I hope that makes sense.
You're so close! makeList can be pretty simple:
def makeList(self, aNode):
if aNode is None:
# Stop recursing here
return []
return self.makeList(aNode.lChild) + [aNode.data] + self.makeList(aNode.rChild)
Basically, make sure you're not trying to recurse past empty nodes. Then return the list of the left tree, the current node, and the list of the right tree.
inOrder prints things but does not return anything, so it's useless for building a list. You need a way to return each node in order. This may be something that your class hasn't covered yet, but check out the yield command.
The basic idea is something like this:
def makeList(self):
return self.lChild.makeList() + [self.data] + self.rChild.makeList()
See how it is essentially the same thing as inOrder?
You have a different structure in your program that makes it a bit harder to implement, but the basic idea is the same.