Leetcode 25. Reverse Nodes in k-Group (链表难度天花板之二)

本文介绍了LeetCode 25题的解题思路,涉及链表翻转,每K个节点为一组进行翻转。通过分析难点并提供解决方案,将复杂问题分解为易处理的部分,适合初学者逐步攻克。同时强调了链表基础知识的重要性,鼓励读者多加练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

题目链接 Leetcode 25. Reverse Nodes in k-Group

翻转LinkedList,以每K个节点为一组翻转,不够K的节点的话就保持不变。

作为链表的难度天花板,这道题依然不是很难。建议看解法之前先练习本题的简单版本LeetCode 206. Reverse Linked List

注意:文章中一切注解皆为Python代码

理解题目

题目非常简单。给定一个链表,每K的节点翻转一次,最后一段不足K个节点就保持不变。这题有两个难点:

  • 如何做到每K个节点翻转一次
  • 如何处理边界情况,如开头段,结尾段

一旦解决这两个问题,这个题目就是一个Easy题。

做过LeetCode 206的人可能是用while循环实现的翻转,如果把while循环换成K次的for循环,再返回相应的起点终点下一个未访问节点,就可以实现每K个节点一次的循环,并且获得操作剩余链表最重要的信息。第一个问题也迎刃而解。

再看第二个问题。我们可以把开头和结尾段分开讨论。

假设一个链表再反转的过程中会有三段,开头段(最终会返回这段的开头),中间段,结尾段(有可能不被翻转)。在这种假设下,开头段和中间段的唯一区别就在于,我们需要返回开头段的首节点;因此,我们把开头段单独拿出来翻转,最终返回的时候提取这段的首节点就好。

结尾段的处理稍微复杂,但也不难。我们算出链表的总长(设为n),再看n % k == 0是否成立,如果成立则结尾段与中间段没有任何区别;如果不成立我们总共可以翻转的节点数为n - n%k个(因为最后一段太短不可以翻转)。

一种特殊情况是n < k,这种情况压根不用翻转,直接返回head就行。

代码实现

class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        def reverse(node, k):                             # 翻转链表中的K的节点
            prev, cur = None, node
            for i in range(k):
                cur.next, prev, cur = prev, cur, cur.next # 这一行等同于一下被注释的四行
                #tmp = cur.next
                #cur.next = prev
                #prev = cur
                #cur = tmp
            start, stop, nxt = prev, node, cur            # 为了便于理解这里重命名一下
            return start, stop, nxt                       # 返回翻转后链表的起点,终点和下一个未访问节点
        
        n, cur = 0, head
        while cur: cur, n = cur.next, n+1                 # 计算链表的总长度
        
        if n < k: return head                             # 如果总长小于K,直接返回首节点,不需要翻转
        
        head, prev_stop, nxt = reverse(head, k)           # 单独处理“开头段”
        for i in range(k, n-n%k, k):                      # 处理“中间段”
            start, stop, nxt = reverse(nxt, k)
            prev_stop.next = start                        # 用上一段的终点连接当前段的起点
            prev_stop = stop                              # 更新终点
        prev_stop.next = nxt                              # 用终点连接未翻转的“结尾段”
        return head                                       # 返回开头段的起点

解题后的思考

尽管标注为Hard,但是由于链表题整体难度不高,这题稍作拆解也是可以比较轻松解决的。

链表翻转是一个超级基础的技能,不会的话建议背下来,或者多练习几遍熟能生巧;面试过程中,链表翻转和树的遍历一样,应该是提笔就写不假思索那种级别的技能。

有的Hard题难在算法,数据结构闻所未闻,这题只需要多想想,大事化小,逐个击破就好;这题也可以说是Hard题之所以Hard的一个典型——很多Easy或者Medium题目的叠加。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值