K个一组反转链表

K个一组反转链表

链表难的地方就在于细节比较多,这道题目的意思就是:

  • 给定一个链表
  • 给定一个k
  • 每k个结点作为一组,然后把这一组进行反转,最后返回反转过的链表

题解

首先,因为可能会修改头节点,所以我们最好加一个dummy结点来作为头节点返回。我们来分解一下整个任务,首先是反转链表,可以使用递归或者迭代

1
2
3
4
5
6
7
8
9
public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode node = reverseList(head.next);
    head.next,next = head;
    head.next = null;
    return node;
}

上述的递归代码可以帮助我们完成反转链表的操作。现在我们来看看怎么完成k个一组的反转吧。

首先是获取当前的k个字符串,假设这里有如下的几个结点:

1
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10

假设给定的k是3,我们来进行模拟一下

首先要反转前3个元素,那么就得断开3与4之间的连接,并且头节点可能会被修改,那么我们最好要加一个dummy结点来进行辅助。

1
dummy -> 1 -> 2 -> 3 断开 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0, head);
        ListNode start = dummy;
        while (true) {
            ListNode end = start;
            for (int i = 0; i < k && end != null; i++) {
                end = end.next;
            }
            if (end == null) break;
            // 记录下一组的开头
            ListNode headOfNextGroup = end.next;
            // 断开
            end.next = null;
            // 第一组开头
            ListNode headOfCurGroup = start.next;
            // 新的头节点
            ListNode endOfCurGroup = reverseList(headOfCurGroup);
            start.next = endOfCurGroup;
            // 连接起来
            headOfCurGroup.next = headOfNextGroup;
            // 移动start指针,移动至最后一个结点
            start = headOfCurGroup;
        }
        return dummy.next;
    }

    private ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode node = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return node;
    }
}
Licensed under CC BY-NC-SA 4.0
花有重开日,人无再少年
使用 Hugo 构建
主题 StackJimmy 设计