Reverse Nodes in k-Group
题目
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
Example:
Given this linked list: 1->2->3->4->5
For k = 2
, you should return: 2->1->4->3->5
For k = 3
, you should return: 3->2->1->4->5
Note:
- Only constant extra memory is allowed.
- You may not alter the values in the list’s nodes, only nodes itself may be changed.
分析
Swap Nodes in Pairs和这道题的区别在于,前者的k
是2,而这道题的k
不确定,作为参数给出。
两道题都要求不能直接改变节点的值,只能改变其指针的指向。
虽然这道题前面说了,k
是正整数且k
的值小于等于链表的长度。但在实际的测试样例中,k
的值有可能大于链表的长度。
这道题的思路也比较简单。就是每k
个节点作为一组,然后reverse
这k
个节点。如果剩下的不足k
个节点,则不进行reverse
。
在一个循环里面,首先判断有没有k
个节点。如果没有,则终止循环;如果有,则对前k
个节点进行reverse
,然后进入下一轮循环。每一轮循环需要记录这k
个节点reverse
之后的head
节点和tail
节点,然后prev
节点(即上一轮循环得到的链表的tail
节点)的next
指向这一轮循环的head
节点。然后更新prev
节点的值为tail
。
如何对长度为k
个节点的链表进行reverse
?
方法还是比较简单的。遍历整个链表,对于某个节点node
,将当前的tail
节点的next
指向node
节点的next
节点,将node
节点的next
指向当前的head
节点,并且更新head
节点的值为node
节点。然后继续遍历下一个节点。
注意:tail
节点的值一直不变,只是其next
节点一直在变化。
如下所示:
假设链表为:1->2->3->4->5
刚开始时 head = tail = 1
然后遍历到下一个节点2,此时链表更新为:2->1->3->4->5,此时head = 2,tail = 1。
......
继续循环下去,知道最后链表更新为:5->4->3->2->1。此时head = 5,tail还是1。
代码如下
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if (k == 1 || head == null) return head;
ListNode result = head;
ListNode prev = null;
ListNode tempHead = head;
ListNode newHead = null;
ListNode tempNode = tempHead;
// 因为第一次prev是null,所以单独处理而不在循环中处理
for (int i = 0; i < k; i++) {
if (tempNode == null) {
return result;
} else {
tempNode = tempNode.next;
}
}
newHead = reverseKNodes(tempHead, k);
result = newHead;
prev = tempHead;
tempHead = tempHead.next;
// 剩下的循环
while (true) {
tempNode = tempHead;
// 判断剩下的时候有k个节点
for (int i = 0; i < k; i++) {
if (tempNode == null) {
return result;
} else {
tempNode = tempNode.next;
}
}
newHead = reverseKNodes(tempHead, k);
prev.next = newHead;
prev = tempHead;
tempHead = tempHead.next;
}
}
// 返回值为倒置之后的头节点,head仍然指向原本的头节点,即倒置后的尾节点
private ListNode reverseKNodes(ListNode head, int k) {
ListNode tempHead = head;
ListNode tempTail = head;
ListNode temp = null;
for (int i = 1; i < k; i++) {
// 交换节点
temp = tempTail.next;
tempTail.next = temp.next;
temp.next = tempHead;
tempHead = temp;
}
return tempHead;
}
}