leetcode hot100 25. K 个一组翻转链表 hard

把这个问题拆解为三个步骤

  1. 找到待翻转的区间:从当前位置开始计数,数出 kkk 个节点。
  2. 如果不足 kkk 个,直接返回,不翻转。
  3. 翻转这 kkk个节点:使用我们熟悉的"翻转链表"逻辑。
  4. 连接前后区间:将翻转后的局部链表重新接回原链表中
python 复制代码
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:


        prehead = ListNode(-1)
        prehead.next = head

        # 当前 k个节点小组的前驱节点
        pre = prehead   # 初始值
        
        # 推进head
        while head:

            # 先组内推进,尾指针前进K个
            tail = pre
            for i in range(k):
                tail = tail.next
                if not tail:    # 即使不足 k 个,也要从最开始的 prehead 返回,而不是当前组pre.next
                    return prehead.next

            # 足k个,记录下一组的起点
            nxt = tail.next

            # 翻转这一小组 [head, tail]
            # 定义一个子函数来处理局部翻转
            head, tail = self.reverse(head, tail)

            # 把翻转后的子链表接回主链表
            pre.next = head
            tail.next = nxt

            # 指针移动,准备处理下一组
            pre = tail
            head = tail.next

        return prehead.next

    # 局部翻转辅助函数
    def reverse(self, head: ListNode, tail: ListNode):
        if not head or not tail:
            return None

        pre = None   # 头节点前面的设一个空节点,先不用指向头节点,因为但反过来之后,头节点就指向none
        cur = head

        while pre != tail:
            tmp = cur.next # 暂存后继节点 cur.next
            cur.next = pre  # 修改 next 引用指向
            pre  = cur
            cur = tmp

        # 翻转后,原来的 tail 变成了新头,原来的 head 变成了新尾
        return tail, head

时间复杂度:O(n)O(n)O(n)

虽然有嵌套循环,但每个节点实际上只被访问了常数次(一次是定位 tail,一次是翻转)。
空间复杂度:O(1)O(1)O(1)

只额外使用了常数个指针,属于原地翻转。

相关推荐
小雅痞1 小时前
[Java][Leetcode middle] 167. 两数之和 II - 输入有序数组
java·算法·leetcode
xin_nai2 小时前
LeetCode热题100(Java)(6)矩阵
java·leetcode·矩阵
圣保罗的大教堂9 小时前
leetcode 1855. 下标对中的最大距离 中等
leetcode
JasmineX-111 小时前
数据结构(笔记)——双向链表
c语言·数据结构·笔记·链表
脱氧核糖核酸__13 小时前
LeetCode热题100——234.回文链表(两种解法)
c++·算法·leetcode·链表
生信研究猿14 小时前
leetcode 416. 分割等和子集
算法·leetcode·职场和发展
6Hzlia15 小时前
【Hot 100 刷题计划】 LeetCode 24. 两两交换链表中的节点 | C++ 精准指针舞步
c++·leetcode·链表
踩坑记录18 小时前
leetcode 92. 反转链表 II 区间反转(不是整条链表反转)
leetcode·链表
6Hzlia18 小时前
【Hot 100 刷题计划】 LeetCode 148. 排序链表 | C++ 归并排序自顶向下
c++·leetcode·链表
im_AMBER19 小时前
Leetcode 162 除了自身以外数组的乘积 | 接雨水
开发语言·javascript·数据结构·算法·leetcode