[英]How to find middle element of linked list in one pass in python?
I am trying to solve a linked list problem, to find the middle element in a single pass using python.我正在尝试解决一个链表问题,使用 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)
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
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?那行得通吗?
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)
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
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.在这里,使用 floor 对我有帮助,否则我的代码会给我错误。
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).它不是遍历一次(和二次半遍历),而是(ab)使用堆栈来模拟半遍历(向后而不是向前)。 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).这不是一个好主意,因为 Python 没有无限增长的堆栈(我希望 Python 能从 Smalltalk 的家伙那里得到这个提示),所以你真的只能处理数百个大小的列表,绝对不能处理数千个(这是 Python3,顺便说一句)。
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".所以我们创建了一个 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.但是一个很好的例子(ab)使用递归和异常来满足只遍历一次的要求。
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
//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())
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:几个重要的点:
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)
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)
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必须有更好的方法来做到这一点我只是从 3,4 天开始编码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.