给你单链表的头结点 head
,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:head = [1,2,3,4,5] 输出:[3,4,5] 解释:链表只有一个中间结点,值为 3 。
思路:只存在两种情况,当链表长度为奇数,快指针到末尾,慢指针指向的就是中中间节点
当链表长度为偶数,快指针指向空,慢指针指向的就是中间节点
代码:
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow=head
fast=head
while fast and fast.next:
slow=slow.next
fast=fast.next.next
return slow
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
思路:本题只是在第一题上加了一些条件,如果存在环,快指针一定会和慢指针相遇。所以相遇就返回true
代码:
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow=head
fast=head
while fast and fast.next:
slow=slow.next
fast=fast.next.next
if slow is fast:
return True
return False
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。
思路:引入数学思维能够增加对这道题的理解
首先,快慢指针一定会在环内相遇,因为特殊情况,当慢指针刚好到入口,快指针在他前面,那么他俩也能在环内相遇,假设a b c
我们可以得到以下结论:环长:b+c
慢指针移动距离:a+b
快指针移动距离:a+b+k(b+c)
又因为快指针移动速度是慢指针两倍2*( a+b)=a+b+k(b+c),所以a-c=(k-1)(b+c)
所以当快慢指针相遇后,慢指针和头指针再一起移动C距离后,头指针到达离入口a-c的位置,慢指针再入口处,a-c=(k-1)(b+c),所以再继续移动,直到头指针和慢指针相遇,他俩一定在入口处相遇
代码:
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow=head
fast=head
while fast and fast.next:
slow=slow.next
fast=fast.next.next
if slow is fast:
while head !=slow:
head=head.next
slow=slow.next
return slow
给定一个单链表 L
的头节点 head
,单链表 L
表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
输入:head = [1,2,3,4] 输出:[1,4,2,3]
思路:首先找到中间节点,反转中间节点和后面的节点,形成head,head2
然后head指向head2,head2指向head.next
然后head置成head.next,head2置成head2.next(注意这里要提前保留后续节点)
最终
直到head2指向中间节点,或者中间节点.next=空
代码部分:
class Solution:
# 876. 链表的中间结点
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
# 206. 反转链表
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
pre, cur = None, head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def reorderList(self, head: Optional[ListNode]) -> None:
mid = self.middleNode(head)
head2 = self.reverseList(mid)
while head2.next:
nxt = head.next
nxt2 = head2.next
head.next = head2
head2.next = nxt
head = nxt
head2 = nxt2
234. 回文链表:序列是向前和向后读都相同的序列
给你一个单链表的头节点 head
,请你判断该链表是否为
回文链表
。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:head = [1,2,2,1] 输出:true
思路:例如一个链表,在经过找到中间节点,反转后续节点后是这样的
这时候head和head2节点都是1,这时候只要一直比较next值是否一样,直到head2是3,没有next节点就可以了
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def middleNode(self, head):
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
def reverseList(self, head):
pre = None
cur = head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def isPalindrome(self, head: Optional[ListNode]) -> bool:
if head is None:
return True
mid = self.middleNode(head)
head2 = self.reverseList(mid)
while head2:
if head.val != head2.val:
return False
head = head.next
head2 = head2.next
return True
注意head2不能改成head,当链表长度为偶数时,head2一边的链表长度小于head,如果用head,会导致head2为空,无法判断其value