25. K 个一组翻转链表
原始题目链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group/
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解题思路:
- 首先是要想出反转链表的操作,给出一个链表的子链表(起始节点),返回反转后的子链表的头结点和尾节点,将这个反转后的子链表再重新链接到原始链表中,重新链接到原始链表就需要知道还没有反转前的子链表起始节点(头结点和尾节点)的前驱节点和后继节点,所以用两个指针分别存储前驱pre和后继ail_next_node。
- 其次是k个一组,走k步,走k步正好走到子链表的尾部,不满足子链表长度就表示,原始链表本身不够长,或者剩余链表的长度不满足k个,这个时候直接返回新的头结点即可。
- 为了方便操作,设置一个dummy节点,它的next指针指向head,最后直接返回dummy.next就是新的头节点。
代码实现:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# 反转一个链表中的一段子链表函数,返回反转后子链表的头结点和尾节点
def reverse(self, head: ListNode, tail: ListNode):
tail_next_node = tail.next
cur_node = head
while tail_next_node != tail:
cur_next_node = cur_node.next
cur_node.next = tail_next_node
tail_next_node = cur_node
cur_node = cur_next_node
return tail, head
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = ListNode(-1)
dummy.next = head
pre = dummy
cur_head = head
while cur_head:
# 初始为pre,走k步,则正好走到子链表的尾节点
tail = pre
# 走k步
for i in range(k):
tail = tail.next
# 判断子链表的长度是否等于k
if not tail:
return dummy.next
# 记录子链表的下一个节点,用于反转后的子链表的尾节点指向该节点
tail_next_node = tail.next
# 反转子链表,并返回新的头结点和尾节点
cur_head, tail = self.reverse(cur_head, tail)
# 把反转后的子链表重新链接指向原链表
pre.next = cur_head
tail.next = tail_next_node
pre = tail
cur_head = tail.next
return dummy.next
参考文献:
https://leetcode-cn.com/problems/reverse-nodes-in-k-group/solution/k-ge-yi-zu-fan-zhuan-lian-biao-by-leetcode-solutio/