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)

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

相关推荐
hold?fish:palm28 分钟前
9 找到字符串中所有字母异位词
c++·算法·leetcode
Sw1zzle1 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木1 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
啦啦啦啦啦zzzz2 小时前
算法:回溯算法
c++·算法·leetcode
zander2583 小时前
114. 二叉树展开为链表
数据结构·链表·深度优先
小肝一下4 小时前
3. 单链表
c语言·数据结构·c++·算法·leetcode·链表·dijkstra
tachibana25 小时前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
To_OC12 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎14 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
To_OC14 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode