![](/img/trans.png)
[英]How to find middle element in a python linked list in a single traversal?
[英]How to find middle element of linked list in one pass in python?
我正在尝试解决一个链表问题,使用 python 在一次传递中找到中间元素。 有人可以查看我的代码并建议执行此操作的最佳方式吗?
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)
我为您合并了所有创建、查找和打印的方法。
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)
输出:
[ 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
这是在路上,它是一次通过,虽然可能没有你想要的那么高效:
def find_middle(node):
list = []
while node:
list.append(node)
node = node.next
return list[len(list)/2]
那行得通吗?
你可以保留两个指针,一个移动速度是另一个的一半。
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)
用于查找链表中间元素的伪代码:-
fast = head
slow = head
while(fast!=null) {
if(fast.next!=null) {
fast = fast.next.next
slow = slow.next
}
else {
break
}
}
// middle element
return slow
以上所有答案都是正确的,但对我来说,这最有效:
def middleNode(self, head: ListNode) -> ListNode:
list=[]
while head:
list.append(head)
head=head.next
return list[floor(len(list)/2)]
在这里,使用 floor 对我有帮助,否则我的代码会给我错误。
好吧,这不是一个好主意。 但它确实满足只遍历一次的约束。 它不是遍历一次(和二次半遍历),而是(ab)使用堆栈来模拟半遍历(向后而不是向前)。 这不是一个好主意,因为 Python 没有无限增长的堆栈(我希望 Python 能从 Smalltalk 的家伙那里得到这个提示),所以你真的只能处理数百个大小的列表,绝对不能处理数千个(这是 Python3,顺便说一句)。
首先,我修改了您的脚本以通过更改值来构建更大的列表:
last = root = Node(1)
for i in range(2, 312):
node = Node(i)
last.next = node
last = node
由于我们正在使用堆栈和递归,因此我们需要一种从深度调用堆栈中突然返回的方法。 所以我们创建了一个 Exception 子类,它实际上更像是一个“通知”而不是“异常”。
class FoundMiddleNode(Exception):
def __init__(self, node):
super().__init__()
self.node = node
现在对于递归函数:
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
为了使用它,我们这样做:
try:
probeForMiddle(root, 0)
except FoundMiddleNode as e:
print(e.node)
不漂亮。 在任何近似生产代码的东西中都不是一个好主意。 但是一个很好的例子(ab)使用递归和异常来满足只遍历一次的要求。
找到中间节点的最好方法是有两个指针:
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())
您可以编写更小的代码来查找中间节点。 显示下面的片段:
def find_middle(node):
half = node
while node and node.next is not None:
node = node.next.next
half = half.next
return half
几个重要的点:
这与詹姆斯和乔丹已经发布的内容非常相似,就它的作用而言,它只是简单一点,我已经添加了解释作为对实际操作的评论
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)
我可能会迟到,但这对我来说最有效。 编写用于创建、查找中点和打印链表的完整代码。
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])
必须有更好的方法来做到这一点我只是从 3,4 天开始编码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.