LeetCode hot 100 — 25. K 个一组翻转链表

题目信息

给你链表的头节点 head ,每 k个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

复制代码
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

复制代码
输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

示例三

**输入:**head = 1,2,k = 2

输出:2,1

思考过程和自写代码

差不多能够自己写出来了。

核心的逻辑也都放在注释里面了,将k个看成一个区间 / 一组,组内进行反转,然后连接组外(最开始只想到了尾部衔接,导致示例提交出了点问题,手写过程后排查出了问题,嘻嘻,好久没感受过这样的古法编程了....)

耗了一点功夫但是写出来了,唯一迭代的地方注释里面也有了,就是如何处理好示例三的边界(到底什么时候退出反转)

自写满分代码(带注释和思维过程)

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]:
        '''
            跟上个题目差不多,从2扩充到了一个更大的群体k. 难点在于是否可以复用逻辑;如果可以复用的话,如何复用逻辑

            初步想法感觉还是需要把k个数据看作一个整体,而且必然不能和上次一样一个一个去修改
            在特定区间内如何反转一段链表,可以参考206反转链表
        '''
        res = ListNode(0, head)
        now_begin = head # 当前区间开始位置
        last_tail = res
        while now_begin: # k <= n,一定可以进行一次反转的
            next_begin = now_begin # next_begin表示下一个需要反转的区间的首个位置
            '''
            原本代码:
                for i in range(k): 
                    next_begin = next_begin.next if next_begin else None # 此时next_begin到达下一个区间需要反转的首个位置
                if next_begin is None: break # 当前区间也即不支持反转
            后因为示例三做出以下的调整,不能一概而论
            '''
            for i in range(k): 
                if not next_begin: return res.next # 先判断再跳转. 执行k次跳转,如果是可以反转的话k次必须都是可以执行的,也就是必须执行k次next_begin = next_begin.next,那么这k次中next_begin必定不是None. 如果next_begin提前进入了none,那就是有问题的(注意不能先跳转再判断,因为我允许next_begin是none,见示例三,此时刚好是k的倍数,允许反转)
                next_begin = next_begin.next
            
            pre = None
            curr = now_begin
            while curr != next_begin:
                next_node = curr.next
                curr.next = pre  # 
                pre = curr
                curr = next_node
            now_begin.next = next_begin # 区间尾部衔接,now_begin为当前区间的最后一个数字,指向下一个区间的起点
            last_tail.next = pre  # 区间首部衔接,上个区间的尾巴指向当前节点的首个数字(如果curr是下一个区间的起点,刚好pre就是原来排列位置当前区间的最后一个 / 现有排列位置的第一个)
            last_tail = now_begin # 当前区间的起点反转以后会变成最后一个
            now_begin = next_begin

        return res.next

代码纯享(复习用)

删去了大段的注释

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]:

        res = ListNode(0, head)
        now_begin = head # 当前区间开始位置
        last_tail = res
        while now_begin: # k <= n,一定可以进行一次反转
            next_begin = now_begin # next_begin表示下一个需要反转的区间的首个位置
        
            for i in range(k): 
                if not next_begin: return res.next
                next_begin = next_begin.next
            
            pre = None
            curr = now_begin
            while curr != next_begin:
                next_node = curr.next
                curr.next = pre  
                pre = curr
                curr = next_node

            now_begin.next = next_begin # 区间尾部衔接,now_begin为当前区间的最后一个数字,指向下一个区间的起点
            last_tail.next = pre  # 区间首部衔接,上个区间的尾巴指向当前节点的首个数字
            last_tail = now_begin # 当前区间的起点反转以后会变成最后一个
            now_begin = next_begin

        return res.next
相关推荐
ocean21032 小时前
2025-2026年AI算法与模型研发面试高频知识点洞察
人工智能·算法·面试
Nil2082 小时前
leetcode 78子集
数据结构·算法·leetcode
en.en..3 小时前
Linux fork() 工作原理
数据结构·算法
地平线开发者4 小时前
bevformer算法模型详细解读
算法
liliangcsdn4 小时前
ICIR权重矩阵如何加权标准化为综合因子
算法
SDWAN_Cheap4 小时前
SD-WAN智能选路技术的算法与实现机制
算法·php·sdwan
不会就选b5 小时前
数据结构之树&&二叉树(二)
数据结构·算法
渡之5 小时前
ArduPilot (APM)滤波器之SlewLimiter 深度解析
算法
zander2586 小时前
LeetCode 1143. 最长公共子序列
开发语言·python·算法