双指针专题
寻找中间结点
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
运用经典的快慢指针
由于快指针的速度是慢指针的两倍,所以当快指针到达链表尾部时,慢指针刚好走过一半的距离,即处于链表的中间位置。
假设链表的长度为 n,快指针每次移动两步,慢指针每次移动一步,那么在快指针到达链表尾部之前,快指针需要移动的步数是慢指针的两倍。
考虑两种情况:
当链表长度 n 为偶数时:
- 快指针需要移动 n/2 步才能到达链表尾部。
- 慢指针每次移动一步,因此需要移动n/2 步才能到达链表的中间位置。
当链表长度 n 为奇数时:
- 快指针需要移动 (n-1)/2 步才能到达链表尾部。由于快指针每次移动两步,所以需要移动 (n-1)/2 次。
- 慢指针每次移动一步,因此需要移动 (n-1)/2 步才能到达链表的中间位置。
这个方法适用于链表长度为奇数和偶数的情况。如果链表长度为奇数,那么慢指针将正好指向中间节点。如果链表长度为偶数,那么慢指针将指向中间两个节点的后一个节点【快指针刚好指向空,慢指针指向最后一个节点】。
def middleNode(self, head):
if head is None:
return None
slow=head
fast=head
while fast and fast.next:
slow=slow.next
fast=fast.next.next
return slow
寻找倒数第k个元素
输入一个链表,要求输出链表的倒数第k个元素。本题从1开始计数。
使用快慢指针,让快指针先向前移动k步,然后快慢指针一起动。当快指针指向末尾时,慢指针所指的位置就是我们想要的元素。
这个方法的原理是,快指针先向前移动 k 步,然后快慢指针同时移动,保持它们之间的距离为 k。当快指针到达链表尾部时,慢指针所指向的节点与快指针之间的距离就是 k,即倒数第 k 个节点。
需要注意的是,如果链表的长度小于 k,那么这个方法将无法找到倒数第 k 个节点。在实际应用中,我们通常会在执行这个算法之前,先判断链表的长度是否大于等于 k。
def getKthFromEnd(self,head:ListNode,k:int)->ListNode:
slow,fast=head,head
for i in range(k):
#range(k):0~k-1
if fast is None:
return None
fast=fast.next
while fast:
slow=slow.next
fast=fast.next
return slow
旋转链表
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
方法一:先让快指针走k步,在让快指针和慢指针一起走,当快指针指向末尾时,慢指针指向应该断开的元素。然后把head接上快指针,再将head指向慢指针后面那一个元素(新链表头部),再断开慢指针。
要注意链表的长度和k的长度,用%来解决问题。
def rotateRight(self, head, k):
fast, slow = head, head
tmp = head
len = 0
while tmp:
tmp = tmp.next
len = len + 1
if k == 0 or len == 0:
return head
k = k % len
for i in range(k):
if fast is None:
return None
fast = fast.next
while fast.next:
fast = fast.next
slow = slow.next
fast.next = head
head = slow.next
slow.next = None
return head
方法二:链表反转(未学待补充)
方法三:直接做,简单粗暴(不懂)
def rotateRight(self, head, k):
if head is None or head.next is None:
return head
num=0
basic_head=head
#统计长度
while head:
if head.next is None:
head.next=basic_head
num+=1
break
num+=1
head=head.next
xx=num-(k%num)
for i in range(xx):
if i==(xx-1):
flag=basic_head
basic_head=basic_head.next
flag.next=None
break
basic_head=basic_head.next#这里这一步为什么,这不变成新链表第二个元素了吗
return basic_head