赞
踩
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
我们需要把链表结点按照 k 个一组分组,所以可以使用一个指针 head 依次指向每组的头结点。这个指针每次向前移动 k 步,直至链表结尾。对于每个分组,我们先判断它的长度是否大于等于 k。若是,我们就翻转这部分链表,否则不需要翻转。
接下来的问题就是如何翻转一个分组内的子链表。翻转一个链表的过程可以参考(206.反转链表)。但是对于一个子链表,除了翻转其本身之外,还需要将子链表的头部与上一个子链表连接,以及子链表的尾部与下一个子链表连接。
因此,在翻转子链表的时候,我们不仅需要子链表头结点 head,还需要有 head 的上一个结点 pre,以便翻转完后把子链表再接回 pre。但是对于第一个子链表,它的头结点 head 前面是没有结点 pre 的。于是我们新建一个结点,把它接到链表的头部,让它作为 pre 的初始值,这样 head 前面就有了一个结点,我们就可以避开链表头部的边界条件。
复杂度分析:
时间复杂度:O(n),其中 n 为链表的长度。head 指针会在 O(⌊n/k⌋) 个结点上停留,每次停留需要进行一次 O(k)的翻转操作。
空间复杂度:O(1),只需要建立常数个变量。
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: # 翻转一个子链表,并且返回新的头与尾 def reverse(self, head: ListNode, tail: ListNode): # 将下一段链表的头节点赋值为当前节点的前一个节点 pre = tail.next # 将头节点指向当前节点 cur = head # 若当前节点的前一个节点不为tail,则进入循环 while pre != tail: temp = cur.next cur.next = pre pre = cur cur = temp # 结束循环,此时子链表的最后一个节点为新子链表的第一个节点,即为最新的pre return pre, head def reverseKGroup(self, head: ListNode, k: int) -> ListNode: # 新建一个结点,把它接到链表的头部,让它作为 pre 的初始值 hair = ListNode(0) hair.next = head pre = hair while head: # 尾节点初值置为pre tail = pre # 查看剩余部分长度是否大于等于k for i in range(k): # 循环结束后tail为要反转的第k个节点 tail = tail.next # 如果不够 k 个结点,则这部分不做反转,直接返回已经反转好的头节点。 if not tail: return hair.next # 记录当前尾节点的下一个节点,也就是下一次要反转的链表的头节点 temp = tail.next # 从head到tail部分进行反转,并返回新的head与tail head, tail = self.reverse(head, tail) # 将反转后的子链表重新接回原链表 pre.next = head tail.next = temp # 更新pre与head pre = tail head = temp return hair.next
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。