【LeetCode 面试经典150题】25. Reverse Nodes in k-Group K个一组翻转链表

25. Reverse Nodes in k-Group

题目大意

Given the head of a linked list, reverse the nodes of the list k at a time, and return the modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as it is.

You may not alter the values in the list’s nodes, only nodes themselves may be changed.

中文释义

给定一个链表的头节点,每次反转 k 个节点,并返回修改后的链表。

k 是一个正整数,且小于或等于链表的长度。如果节点数不是 k 的倍数,则最后剩下的节点应保持原样。

你不能更改链表节点中的值,只能更改节点本身。

示例

Example 1:
在这里插入图片描述

Input: head = [1,2,3,4,5], k = 2
Output: [2,1,4,3,5]

Example 2:
在这里插入图片描述

Input: head = [1,2,3,4,5], k = 3
Output: [3,2,1,4,5]

限制条件

  • 链表中的节点数为 n。
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

进阶问题

你能在 O(1) 额外内存空间中解决这个问题吗?

解题思路

方法

即在给定的单链表中每 k 个节点为一组进行反转。该方法使用迭代方式。

  1. 边界条件检查

    • 如果头节点 head 为空或 k 为 1,直接返回 head
  2. 使用哨兵节点

    • 创建一个哨兵节点 sentinel 并将其 next 指向 head
  3. 初始化指针和计数

    • 创建指针 pre 指向哨兵节点,cur 指向 head。初始化计数变量 count
  4. 计算节点总数

    • 遍历链表,计算节点总数并存储在 count 中。
  5. 按组反转节点

    • count 大于等于 k 时,进行反转操作:
      • cur 设置为 pre 的下一个节点。
      • 对每个分组内的节点进行反转:
        • 通过迭代更新 curnexcur 的下一个节点)的 next 指针,将节点逐个插入到 pre 的后面。
      • 更新 pre 为当前分组反转后的最后一个节点。
      • 减少 count 以处理下一个分组。
  6. 返回结果

    • 最后返回哨兵节点 sentinelnext 作为结果,同时删除哨兵节点防止内存泄漏。

代码

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (head == nullptr || k == 1) return head;

        ListNode *sentinel = new ListNode(0);
        sentinel->next = head;
        
        ListNode *pre = sentinel, *cur = head, *nex;
        int count = 0;
        while (cur) {
            count++;
            cur = cur->next;
        }

        while (count >= k) {
            cur = pre->next;
            nex = cur->next;
            for (int i = 1; i < k; ++i) {
                cur->next = nex->next;
                nex->next = pre->next;
                pre->next = nex;
                nex = cur->next;
            }
            pre = cur;
            count -= k;
        }

        ListNode *result = sentinel->next;
        delete sentinel; // 防止内存泄漏
        return result;
    }
};
  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值