1

题目描述

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

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明 :

  • 你的算法只能使用常数的额外空间。
  • 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

ListNode结构

class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
    }
}

解决方法

使用4个指针反转链表

  • start下一次循环的开始节点
  • kStep提前走k步
  • cur当前要移动的节点
  • pre固定的开始节点
例如:
list = 1 -> 2 -> 3 -> 4 -> 5, k = 3
首先使用虚拟头节点简化操作
dummy  ->  1  ->  2  ->  3  ->  4  ->  5

第一次反转链表过程如下
dummy  ->  1  ->  2  ->  3  ->  4  ->  5
 pre      cur          kStep
         start

dummy  ->  2  ->  3  ->  1  ->  4  ->  5
 pre      cur   kStep  start

dummy  ->  3  ->  2  ->  1  ->  4  ->  5
 pre      cur          start
         kStep

第二次反转遍历过程如下
dummy  ->  3  ->  2  ->  1  ->  4  ->  5  ->  null
                        pre   start           kStep

kStep为null退出循环
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode start = dummy;
        while (true) {
            ListNode kStep = start, pre = start, cur;
            start = pre.next;
            for (int i = 0; i < k && kStep != null; i++)
                kStep = kStep.next;
            if (kStep == null)
                break;
            for (int i = 0; i < k - 1; i++) {
                cur = pre.next;
                pre.next = cur.next;
                cur.next = kStep.next;
                kStep.next = cur;
            }
        }

        return dummy.next;
    }

本文首发: https://lierabbit.cn/2018/09/...


LieRabbit
920 声望2.6k 粉丝

有些梦虽然遥不可及,但并不是不可能实现,只要我足够的强