链表反转[小专题]
刚刚开始刷题的小白一只,多多指教!
1. 反转整个链表
Leetcode 206 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
递归求解,要将递归函数抽象成概念,方便理解。reverseList
函数功能是反转一个以head
为头节点的链表。关注点:使用函数反转head.next
之后,只需要聚焦对于head
的处理就可以。
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 可以使用递归的思路解决反转链表的问题
if not head or not head.next:
return head
if head and not head.next:
return head
node = self.reverseList(head.next)
"""此时head的下一个节点是尾部节点,需要的操作时将head变成尾部节点的下一个节点"""
head.next.next = head
"""之后将head.next = None防止形成循环链表"""
head.next = None
return node
2. 反转前N个节点
反转前N
个节点和反转整个链表逻辑上基本类似,唯一不同在于本题需要一个successor
指针,这个指针用于指向第N+1
个节点。反转完前N
个节点之后,需要将前N
个的尾节点指向successor
,““连接起来””。
"""使用reverseN 反转整个链表"""
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return None
cur = head
cnt = 0
while cur:
cnt += 1
cur = cur.next
return self.reverseN(head, cnt)[0]
"""反转前N个节点"""
def reverseN(self, head, n):
"""如何获得successor指针指向的位置"""
if n == 1:
successor = head.next
return head, successor
new_head, successor = self.reverseN(head.next, n - 1)
head.next.next = head
head.next = successor
return new_head, successor
3.反转链表某个区间内的节点
Leetcode 92 给你单链表的头指针 head 和两个整数 left 和 right,
其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。
这个题目可以借助2中的reverseN
函数,寻找到left
节点作为头节点,之后使用reverseN
反转前right-left+1
个节点。注意在left
的前一个位置留一个指针,方便后续连接,因此引入一个虚拟头节点dum
是很有必要的。在学习labuladong代码的时候发现第二个函数有递归的写法,但我个人更容易理解直接while
遍历的写法。
class Solution:
def reverseN(self, head, n):
if n == 1:
successor = head.next
return head, successor
node, successor = self.reverseN(head.next, n-1)
head.next.next = head
head.next = successor
return node, successor
"""递归的写法"""
# def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
# if left == 1:
# return self.reverseN(head, right)[0]
# head.next = self.reverseBetween(head.next, left-1, right-1)
# return head
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
cur = dum = ListNode(-1)
dum.next = head
cnt = -1
while cur:
cnt+=1
if cnt+1 == left:
pre = cur
node = cur.next
break
cur = cur.next
pre.next = self.reverseN(node, right-left+1)[0]
return dum.next
4. K 个一组翻转链表
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
# TODO: