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)

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

相关推荐
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
To_OC3 天前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
To_OC3 天前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode
To_OC4 天前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
To_OC6 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
To_OC7 天前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
想吃火锅100513 天前
【leetcode】121.买卖股票的最佳时机js/c++
算法·leetcode·职场和发展
凌波粒13 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
疯狂成瘾者13 天前
Java 集合 LinkedList 详解:链表结构、常用方法和队列使用
java·开发语言·链表