Reputation: 16940
I am trying to solve a linked list problem, to find the middle element in a single pass using python. Could someone please review my code and suggest the best manner to do this?
class Node(object):
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __str__(self):
return str(self.data)
def print_nodes(node):
while node:
print node
node = node.next
def find_middle(node):
while node:
current = node
node = node.next
second_pointer = node.next
next_pointer = second_pointer.next
if next_pointer is None:
return "Middle node is %s" % str(current)
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node5 = Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
print find_middle(node1)
Upvotes: 6
Views: 12699
Reputation: 1
I might be little late but this works best for me. Writing complete code for creating, finding the midpoint & printing the linked list.
class Node:
'''
Class to create Node and next part of the linked list
'''
def __init__(self,data):
self.data = data
self.next = None
def createLL(arr):
'''
linked list creation
'''
head = Node(arr[0])
tail = head
for data in arr[1:]:
tail.next = Node(data)
tail = tail.next
return head
def midPointOfLL(head):
'''
Here, i am using two pointers slow and fast, So idea is fast will be 2 times faster than slow pointer
and when fast reaches the end of the linked list slow pointer will be exactly in the middle.
'''
slow = head
fast = head
if head is not None:
while (fast.next is not None) and (fast.next.next is not None):
slow = slow.next
fast = fast.next.next
return slow
def printLL(head):
curr = head
while curr :
print(curr.data,end = "-->")
curr = curr.next
print('None')
arr = list(map(int,input().split()))
head = createLL(arr)
midPoint = midPointOfLL(head)
print(midPoint.data)
printLL(head)
Upvotes: 0
Reputation: 833
All of the above answers are right but for me, this worked best:
def middleNode(self, head: ListNode) -> ListNode:
list=[]
while head:
list.append(head)
head=head.next
return list[floor(len(list)/2)]
Here, using floor helped me otherwise my code gave me errors.
Upvotes: 1
Reputation: 22382
This is very similar to what James and Jordan have posted already, it's just little simpler in terms of what it does and I've added explanation as comments to what's actually doing
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
# loop through the items and check for next items using two pointers (fast and slow)
# set the speed for fast twice higher than the slow pointer so when when fast reaches
# the end the slow would be in the middle
def find_middle(head ):
fast = slow = head
#slow = head
while fast.next != None and fast.next.next != None:
fast = fast.next.next
slow = slow.next
# slow is now at the middle :)
print (slow.data )
#setup data
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node5 = Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
find_middle(node1)
Upvotes: 0
Reputation: 2051
You can write a smaller code for finding the middle node. Showing the snippet below:
def find_middle(node):
half = node
while node and node.next is not None:
node = node.next.next
half = half.next
return half
Few important points:
Upvotes: 0
Reputation: 105
//Linked list
ll = {'A': ["data", "B"],
'B': ["data", "C"],
'C': ["data", "D"],
'D': ["data", "E"],
'E': ["data", None]}
def find_next_node(node="A"):
return ll[node][1] if ll[node][1] else None
def find_mid_node(head="A"):
slow = head
fast = head
while(fast!=None):
for i in range(2):
if find_next_node(fast):
fast = find_next_node(node=fast)
else:
return slow
for j in range(1):
slow = find_next_node(node=slow)
print (find_mid_node())
Upvotes: 0
Reputation:
The best way to find the middle node is to have two pointers:
P1 = root
P2 = root
While not p2.next == Null:
P1 =p1.next
P2 =P2.next.next
Upvotes: 0
Reputation: 595
list=['ok','go','no','poi','duo','ok','go','nah']
b=0
b=int(len(list)/2) #print the middle element change .5 values
print(list[b])
if((len(list)%2)==0): #if list is of even number print both middle values
print(list[b+1])
there must be a better way to do it i just start coding from like 3,4 day
Upvotes: -1
Reputation:
I merged all the methods for you creating, finding and printing.
class Node(object):
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __str__(self):
return str(self.data)
def create_linked_list(n):
"""Creating linked list for the given
size"""
linked_list = Node(1)
head = linked_list
for i in range(2, n):
head.next = Node(i)
head = head.next
return linked_list
def print_linked_list(node):
"""To print the linked list in forward"""
while node:
print '[',node,']','[ref] ->',
node = node.next
print '-> None'
def find_middle1(node):
tick = False
half = node
while node:
node = node.next
if tick:
half = half.next
tick = not tick
return "Middle node is %s" % str(half)
def find_middle2(node):
list = []
while node:
list.append(node)
node = node.next
return "Middle node is %s" % str(list[len(list)/2])
node = create_linked_list(10)
print_linked_list(node)
print find_middle1(node)
print find_middle2(node)
Output:
[ 1 ] [ref] -> [ 2 ] [ref] -> [ 3 ] [ref] -> [ 4 ] [ref] -> [ 5 ] [ref] -> [ 6 ] [ref] -> [ 7 ] [ref] -> [ 8 ] [ref] -> [ 9 ] [ref] -> -> None
Middle node is 5
Middle node is 5
Upvotes: 8
Reputation: 22252
OK, this is NOT a good idea. But it DOES satisfy the constraint of traversing only once. Instead of traversing once (and a secondary half traversal), it (ab)uses the stack to emulate the half traversal (backwards instead of forwards). It's not a good idea, because Python doesn't have an infinitely growable stack (I wish Python would take a cue from the Smalltalk guys on this one), so you really can only handle lists in the size of hundreds, definitely not thousands (this is Python3, btw).
First I modified your script to build bigger lists with the change of a value:
last = root = Node(1)
for i in range(2, 312):
node = Node(i)
last.next = node
last = node
Since we're using the stack and recursion, we need a way to return abruptly out of a deep call stack. So we create an Exception subclass, which is really more of a "notification" than an "exception".
class FoundMiddleNode(Exception):
def __init__(self, node):
super().__init__()
self.node = node
Now for the recursive function:
def probeForMiddle(node, length):
if node.next is None: #recursion stopper
return length
#call recursively
lengthToEnd = probeForMiddle(node.next, length + 1)
#is my distance from start half of what is being returned recursively as the full length?
if (lengthToEnd // 2) - length == 0:
raise FoundMiddleNode(node) #throw an exception to abort the rest of the stack walk
return lengthToEnd
And to use it we do:
try:
probeForMiddle(root, 0)
except FoundMiddleNode as e:
print(e.node)
Not pretty. Not a good idea in anything approximating production code. But a decent example of (ab)using recursion and exceptions to fill the requirement of only traversing once.
Upvotes: 0
Reputation: 6246
pseudo code for finding middle element of linked list : -
fast = head
slow = head
while(fast!=null) {
if(fast.next!=null) {
fast = fast.next.next
slow = slow.next
}
else {
break
}
}
// middle element
return slow
Upvotes: 2
Reputation: 1499
You could keep two pointers, one that moves half as fast as the other.
def find_middle(node):
tick = False
half = node
while node:
node = node.next
if (tick):
half = half.next
tick = not tick
return "Middle node is %s" % str(half)
Upvotes: 4
Reputation: 5381
Here's on way, it's one pass, though probably not as efficient as you'd like:
def find_middle(node):
list = []
while node:
list.append(node)
node = node.next
return list[len(list)/2]
does that work?
Upvotes: 4