LongDz 的数字文墨提案

25. K 个一组翻转链表

3 min

题目

25. K 个一组翻转链表 困难

解法:头插翻转

思路

核心思想是使用头插法分组翻转链表。通过dummy节点简化头节点处理,对每组节点执行k-1次头插操作实现翻转。

正确性在于:头插法将组内第2至k个节点依次插入组前,自然形成逆序;组间通过pre指针衔接确保连接正确,且剩余不足k的组因不进入循环保持原序。

  • Step 1: 计算链表长度并确定翻转组数
  • Step 2: 初始化dummy节点,pre指向dummy,cur指向头节点
  • Step 3: 循环组数次,每组执行k-1次头插(将cur->next移到pre后)
  • Step 4: 更新pre为当前组尾节点,cur指向下一组头节点

复杂度

  • 时间复杂度: O(n)O(n),遍历链表两次(计算长度和翻转操作),每个节点被处理常数次。
  • 空间复杂度: O(1)O(1),仅使用dummy节点和固定数量指针。

代码

/**
 * 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 (!head || k == 1) return head;

        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        
        ListNode* cur = head;
        int length = 0;
        while (cur) {
            length++;
            cur = cur->next;
        }

/**
 * 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 (!head || k == 1) return head;

        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        
        ListNode* cur = head;
        int length = 0;
        while (cur) {
            length++;
            cur = cur->next;
        }

        ListNode* pre = dummy;
        cur = head;
        ListNode* nex = nullptr;

        // 对每 k 个节点进行一组翻转
        for (int i = 0; i < length / k; i++) {
            
            for (int j = 1; j < k; j++) {
                nex = cur->next;
                cur->next = nex->next;
                nex->next = pre->next;
                pre->next = nex;
            }
           
            pre = cur;
            cur = cur->next;
        }

        return dummy->next;
    }
};