• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【翻转链表】LeetCode 25. K 个一组翻转链表

题目

https://leetcode.cn/problems/reverse-nodes-in-k-group/description/

题解

首先分析特殊情况,当链表长度 \(n\) 与 \(k\) 相等的情况。以测试用例 \(head = [0,1,2,3], k = 4\) 进行分析:

使用指针 \(first\) 指向头结点,指针 \(last\) 指向尾结点:

容易看出,将指针 \(first\) 依次后移到指针 \(last\) 所指向的节点的前一个节点为止,并使用头插法逐个插入到指针 \(last\) 所指向的节点之后,即可实现 \(n == k\) 的情况下的链表翻转:

  1. 首先使用指针 \(node\) 指向 \(first -> next\),以保证可以遍历链表(这个较为简单就不画出了)。
  2. 将指针 \(last -> next\) 赋予指针 \(first -> next\)
  3. 将指针 \(first\) 赋予指针 \(last -> next\)
  4. 随后,将指针 \(node\) 赋予 \(first\)
  5. 重复上述步骤1~4,直到指针 \(first\) 与指针 \(last\) 指向的节点是相同的节点就立刻停止,最后得到以下链表:

现在拥有了翻转整个链表的思路,进一步思考如何只翻转链表中的 \(k(k < n)\) 个节点?

以测试用例 \(head = [0,1,2,3], k = 2\) 进行分析:

  1. 首先让指针 \(first\) 指向第 \(1\) 个节点,指针 \(last\) 指向第 \(k = 2\) 个节点:
  2. 按照之前分析的思路,经过翻转,可以得到:
  3. 此时无法简单重复之前的步骤,而是需要让指针 \(first\) 指向第 \(k + 1 = 3\) 个节点,让指针 \(last\) 指向第 \(k + k = 4\) 个节点:
  4. 此时,尝试使用 \(n == k\) 时的翻转链表的思路进行翻转,得到的结果如下:

    容易发现,使用 \(n == k\) 时的翻转链表的思路,对 \(k < n\) 的情况并不适用。进一步思考问题出在哪里?
    答:问题出在第 \(k + 1 = 3\) 个节点之前的节点的指针 \(next\) 未指向第 \(k + k = 4\) 个节点。
  5. 因此,需要额外维护指针 \(first\) 指向的节点之前的第一个节点 \(pre\),并在每次执行翻转操作后,就将最新的指针 \(first\) 赋予指针 \(pre -> next\)。为了统一操作,使整个链表的最前面 \(k\) 个节点也能用节点 \(pre\) 维护,可以额外引入一个节点作为 \(pre\) 节点,将 \(pre -> next\) 初始化为 \(head\)。
  6. 最后,可以使用一个 int 型的整数去维护节点个数,当该整数为 \(k\) 的整数倍时,就将这连续的 \(k\) 个节点进行翻转,这样就可以实现 \(k\) 个一组的翻转链表操作了。

参考代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (k == 1) return head;
        ListNode* f = new ListNode(), * l, * right;
        f -> next = head;
        right = head;
        for (int i = 1; ; ++ i) {
            if (right -> next == nullptr && i % k) break;
            if (i % k == 0) {
                l = f -> next;
                while (f -> next != right) {
                    ListNode* node = f -> next -> next;
                    f -> next -> next = right -> next;
                    right -> next = f -> next;
                    f -> next = node;
                }
                if (i == k) {
                    head = f -> next;
                }
                f = l;
                right = f -> next;
                if (right == nullptr) break;
            } else {
                right = right -> next;
            }
        }
        return head;
    }
};

若是最后剩余的节点不足 \(k\) 个,也需要进行翻转的,则使用如下代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (k == 1) return head;
        ListNode* f = new ListNode(), * l, * right;
        f -> next = head;
        right = head;
        bool flag = true;
        for (int i = 1; ; ++ i) {
            if (i % k == 0 || right -> next == nullptr) {
                l = f -> next;
                while (f -> next != right) {
                    ListNode* node = f -> next -> next;
                    f -> next -> next = right -> next;
                    right -> next = f -> next;
                    f -> next = node;
                }
                if (flag) {
                    flag = false;
                    head = f -> next;
                }
                if (right -> next == nullptr) break;
                f = l;
                right = f -> next;
                if (right == nullptr) break;
            } else {
                right = right -> next;
            }
        }
        return head;
    }
};

posted on 2025-04-16 19:33  RomanLin  阅读(40)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3