单链表:链表中的节点每k个一组进行翻转

本文介绍了如何将链表中的节点每k个一组进行翻转,通过定义prev、start和next指针,实现空间复杂度为O(1)的翻转操作。并提供了翻转过程的详细步骤和示例。

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

链表中的节点每k个一组进行翻转

题目:
        将给出的链表中的节点每k个一组翻转,返回翻转后的链表。
        如果链表中的节点数不是k的倍数,将最后剩下的节点保持原样。
        不能更改节点中的值,只能更改节点本身。
        要求空间复杂度为O(1)

示例:
        给定的链表是:1→2→3→4→5
        对于k = 2,你应该返回:2→1→4→3→5
        对于k = 3,你应该返回:3→2→1→4→5

思路:
        ① 题目要求我们每k个节点一组进行翻转。所以我们必须要明确每次要翻转的节点的范围。
        ② 对于我们确定好的范围,我们要进行该范围内的翻转链表。

        ③ 翻转链表后,又有新的问题,翻转后的链表怎么链到原链表中呢?我们可以通过指针来完成该操作。定义prev指针,用来保存一组待翻转链表的上一个节点,定义start,用来保存待翻转链表的第一个节点。再定义一个指针 next,用来保存待翻转链表的最后一个节点的下一个节点。这样,我们就能轻而易举的将翻转后的链表链到原链表中。

图示:
        ① 图示为链表初始状态,其中dummy是头结点,无实际意义。end、prev分别指向dummy。我们用 k = 2 来举例。
在这里插入图片描述
        ② 通过end,我们找到了待翻转链表的最后一个节点,然后我们需要找到待翻转链表的第一个节点,定义start指针,指向待翻转链表的第一个节点,然后我们还需要知道待翻转链表的最后一个节点的下一个节点,便于下一次我们找到新的一组待翻转链表的第一个节点。我们使用next指针记录待翻转链表的最后一个节点的下一个节点。如图所示:
在这里插入图片描述
        此时,翻转start、end范围内的节点,注意在翻转之前,我们应该将end.next置为null。这样才能准确地进行翻转。翻转结果如下图所示:
在这里插入图片描述
        接着我们将start所指向的节点的next域指向next,**prev指向的节点的next域指向我们新翻转后链表的第一个结点。**如下图所示:
在这里插入图片描述
        紧接着,我们调整end、prev、start、以便下一组链表翻转。此时应该将prev 指向start。 end指向start。 然后继续翻转下一组链表。继续通过for循环找到下一组链表的最后一个结点,如下图所示:

在这里插入图片描述
        翻转start、end范围内的结点,如下图所示:
在这里插入图片描述
        prev.next置为新翻转后的链表的第一个结点,start.next指向next。end、prev都指向start。如下图所示:
在这里插入图片描述
        继续重复上面的步骤,最后链表为:
在这里插入图片描述
代码实现:

    public ListNode reverseKGroup (ListNode head, int k) {
        if(head == null) return null;
        ListNode dummy = new ListNode(0); //链表头结点,无实际意义
        ListNode prev = dummy;
        ListNode end = dummy;
        dummy.next = head;
        while(end!=null){
            for(int i = 0; i<k && end!=null; i++){
                end = end.next;
            }
          
            if(end == null) break;
            ListNode next = end.next; //记录下一组链表的第一个节点
            end.next = null; //这组链表先与后面的链表断开连接。
            ListNode start = prev.next; // 记录待翻转链表的第一个节点,用于reverse()函数使用。
            prev.next = reverse(start); //reverse()函数返回翻转后链表的第一个节点。
            
            // 记录下一组链表的start、end以及其前一个节点。
            start.next = next; //新翻转的链表最后一个节点链接后面的节点。
            prev = start;
            end = prev;
            
        }
        return dummy.next;
    }
    
    private ListNode reverse(ListNode head){
        if(head == null) return null;
        ListNode cur = head;
        ListNode next = null;
        ListNode prev = null;
        while(cur!=null){
            next = cur.next;
            cur.next = prev;
            prev = cur;
            cur = next;
        }
        return prev;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值