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
相关推荐
BYSJMG11 小时前
计算机毕业设计选题推荐:基于大数据的快递物流运营数据分析与可视化,Spark与K-Means
大数据·算法·数据分析·spark·课程设计
阳明山水12 小时前
因果一致性正则化实战解析
人工智能·深度学习·算法·机器学习·架构
黄金龙PLUS13 小时前
5个1024比特大状态置换算法的设计与分析
算法·网络安全·密码学·哈希算法·同态加密
心中有你021413 小时前
C语言埃氏筛法(素数筛选)
c语言·数据结构·算法
Omics Pro14 小时前
Cell封面|衰老生物学开源AI工具包
数据库·人工智能·算法·机器学习·自然语言处理
UIU11417 小时前
递归算法与汉诺塔
c++·学习·算法·c#·递归
用户979984807181 天前
200 行代码写一个能跑的 AI Agent:不依赖任何框架,只靠 tool-calling 原理
算法
threerocks1 天前
【Muse实战】X 流量作战室搭建保姆级教程 - 拥有你自己的运营团队
算法
GreenTea1 天前
深度拆解 ScienceBuddy:如何用“双层递归自进化”构建高可靠科研 Agent Harness
前端·后端·算法
花椒技术1 天前
2.46 秒生成 5 秒视频:拆解 H3 Max 的模型、推理栈与硬件协同
算法·音视频开发·视频编码