LeetCode(25)K个一组反转链表

本文深入解析LeetCode第25题“K个一组反转链表”的解题思路,介绍如何使用栈进行链表反转,并探讨了不使用额外空间的解决方案。

LeetCode(25)K个一组反转链表

一个体面人的刷题之旅

题目描述

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

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

题目分析

首先,这是一道链表反转题目,我们要对操作动作数据结构的关联敏感,一看到翻转,就想到先进后出啊,这样就顺序反转了不嘛!一提到先进后出!!------

解法一 利用栈

既然让我们每K个节点反转那么我们把原链表的每K个节点依次入栈,在把我们K个节点依次出栈,循环这样做,直到将所有的节点反转完成,(这里要考虑的是当剩余的节点小于K时,我们就不改变顺序了,所以这种情况是我们的一个分支)。

talk is cheap,show me the code!

所有的链表题我们都需要定义一个哑巴节点来指向我们的入参节点,这样我们在最后可以直接返回哑巴节点的next返回我们操作的链表头就可以了。(我开始的时候真的不懂为什么,后来做多了慢慢就懂了。所以大家加油,别放弃 不会可以 多做几遍,在不会 就在做,实在不行 锻炼身体 找阿姨去把

ListNode dumy = new ListNode(0);
dumy.next = head; 

然后,这里我们要定义一个current节点,通过这个节点我们可以做到不改变dumy指针的情况下,对head进行翻转。

ListNode current = dumy;

这里还需要定义个next节点,表示我们正在翻转的节点,这个节点从我们要翻转链表的头部开始。

ListNode next = dumy.next

初始化一个栈容器用来翻转链表

Stack<ListNode> context = new Stack<ListNode>();

接下来就是遍历节点,把它们放到栈里,然后提取翻转。

while(next != null){//循环终止条件,当操作节点是null,也就是遍历到了链表末尾了
//这里把节点放入栈,这里要满足的条件是节点不能未null,并且循环次数小于翻转的个数
    for(int i =0; i < k && next!= null; i++){
        context.push(next);//放入
        next= next.next;//要翻转的节点,更新到下一个节点
    }
    //判断特殊情况,也就是放入栈中的节点数量小于k,说明我们遍历到最后了,剩余的节点不满足一次翻转的数量,我们直接返回dumy.next,终止操作就可以了。
    if(context.size() != k) return dumy.next;
    //出栈,翻转,
    while(context.size()!= 0){
                current.next = context.pop();
                current = current.next;
            }
    //这里是将当前节点指向剩余未翻转节点,这样我们在如果剩余长度不满足k的情况下就可以直接返回了。
            current.next = next;
}

整体流程就这样,第一次写,大家见谅。下面贴出全部代码:

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dumy = new ListNode(0);
        dumy.next = head;
        ListNode current = dumy;
        ListNode next = current.next;
        Stack<ListNode> context = new Stack<ListNode>();
        while(next != null){
            for(int i= 0; i < k && next!=null; i++){
                context.push(next);
                next = next.next;
            }
            if(context.size() != k) return dumy.next;
            while(context.size()!= 0){
                current.next = context.pop();
                current = current.next;
            }
            current.next = next;
        }
        return dumy.next;
    }
}

大家考虑下,我们可不可以不用额外空间实现呢?

解法二

大家考虑下,我们可不可以不用额外空间实现呢?

待续。。。

在解决 LeetCode 中的 K 个一组反转链表问题时,关键在于理解如何在不改变节点值的情况下调整节点顺序,并确保每组 K 个节点被正确地反转。以下是一个详细的解决方案说明: ### 解决方案概述 1. **初始化**:创建一个虚拟头节点 `dummy` 来简化边界情况处理,并将 `dummy.next` 指向原始链表的头节点。 2. **检查剩余节点数**:在每次循环开始前,检查是否还有至少 K 个节点可以反转。这通过移动指针 `temp` 遍历当前段落来实现。 3. **反转指定数量的节点**:一旦确认有足够的节点进行反转,则执行反转操作。在此过程中,需要维护三个指针(`prev`, `curr`, 和 `nextNode`)来进行标准的链表反转。 4. **连接反转后的子链表**:完成局部反转后,需要将其与前面已经处理好的部分以及后续未处理的部分正确连接起来。 ### Python 实现代码 ```python class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def reverseKGroup(self, head: ListNode, k: int) -> ListNode: if not head or k <= 1: return head dummy = ListNode(-1) dummy.next = head temp = dummy while temp: temp = self.reverseNextK(temp, k) return dummy.next def reverseNextK(self, head: ListNode, k: int) -> ListNode: # Check if there are k nodes left temp = head for _ in range(k): if not temp.next: return None temp = temp.next # Reverse k nodes node = head.next prev = head curr = head.next for _ in range(k): next_node = curr.next curr.next = prev prev = curr curr = next_node # Connect with head and tail node.next = curr head.next = prev return node ``` 上述代码首先定义了一个辅助函数 `reverseNextK` 来负责反转从给定头节点之后开始的 K 个节点,并返回新的尾部节点以便于主函数中更新下一个要处理段落的位置。整个算法的时间复杂度为 O(n),其中 n 是链表中的节点总数;空间复杂度为 O(1),符合题目要求仅使用常量级别的额外内存[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值