题目地址:
https://www.lintcode.com/problem/reverse-nodes-in-k-group/description
给定一个链表,再给定一个数 k k k,要求 k k k个 k k k个翻转链表。若不足 k k k个则不翻转。
思路是另开一个专门的函数用于翻转prev接下来的 k k k个节点,同时返回翻转后的 k k k个节点的最后一个,这样就可以以这最后一个节点作为prev继续做翻转;若不足 k k k个则返回null。很显然一开始的prev就设置为dummy node接在head前面即可。至于如何翻转 k k k个节点,方法是将这 k k k个节点的最后一个节点与之后的节点断开,然后做翻转,然后再将翻转后的 k k k个节点的最后一个连到后面去,重新接起来。代码如下:
public class Solution {
/**
* @param head: a ListNode
* @param k: An integer
* @return: a ListNode
*/
public ListNode reverseKGroup(ListNode head, int k) {
// write your code here
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
while ((prev = reverseK(prev, k)) != null) {
}
return dummy.next;
}
private ListNode reverseK(ListNode prev, int k) {
// prev -> n1 -> n2 -> ... -> nk -> tail
ListNode nk = prev;
for (int i = 0; i < k; i++) {
nk = nk.next;
if (nk == null) {
return null;
}
}
// 找到要翻转的最后一个节点的后面一个节点,然后断开
ListNode tail = nk.next;
nk.next = null;
// 记录一下翻转后的k个节点中的最后一个节点,也就是翻转前的第一个节点
ListNode n1 = prev.next;
prev.next = reverse(prev.next);
// 连上去
n1.next = tail;
return n1;
}
private ListNode reverse(ListNode head) {
ListNode prev = null;
while (head != null) {
ListNode tmp = head.next;
head.next = prev;
prev = head;
head = tmp;
}
return prev;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。