博文中会简要介绍Leetcode P0025题目分析及解题思路。
“Reverse Nodes in k-Group”是一道原型题,主要考察了链表的删除,插入和反转操作。p0024是其简化版。
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.
这道题的思路比较直接,时间复杂度是O(n)。用prev
指针确定kGroup的起点的前缀结点,用slow
来翻转kGroup内的所有结点(除了两端),用fast
来定位该kGroup的终点,然后当所有除了两端结点以外的kGroup结点都翻转结束,处理两端的链指向,然后重新定位下一个kGroup,直到所有可反转的kGroup全部翻转结束
以下是Java的题解代码实现。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null || k == 1)
return head;
ListNode dummy = new ListNode(0, head);
ListNode prev = dummy, slow = head, fast = dummy;
fast = this.isReverseEnabled(fast, k);
while (fast != null) {
ListNode temp = slow;
// 反转kgroup中除了两端以外的所有结点
while (slow != fast) {
ListNode post = slow.next;
slow.next = temp;
temp = slow;
slow = post;
}
// 改变kgroup两端结点的链指向
prev.next.next = fast.next;
slow.next = temp;
temp = prev.next;
prev.next = fast;
// 重新归位寻找下一个kgroup
fast = temp;
slow = fast.next;
prev = fast;
fast = this.isReverseEnabled(fast, k);
}
return dummy.next;
}
private ListNode isReverseEnabled(ListNode fast, int k) {
for (int counter=0; counter<k; ++counter) {
if (fast == null) {
break;
}
fast = fast.next;
}
return fast;
}
}
以下是C++的题解代码实现。
/**
* 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 == NULL || k == 1)
return head;
ListNode *dummy = new ListNode(0, head);
ListNode *prev = dummy, *slow = head, *fast = dummy;
this->IsReverseEnabled(fast, k);
while (fast) {
ListNode *temp = slow;
while (slow != fast) {
ListNode *post = slow->next;
slow->next = temp;
temp = slow;
slow = post;
}
prev->next->next = fast->next;
fast->next = temp;
temp = prev->next;
prev->next = fast;
prev = fast = temp;
slow = fast->next;
this->IsReverseEnabled(fast, k);
}
return dummy->next;
}
private:
void IsReverseEnabled(ListNode *&fast, const int k) {
for (int counter=0; counter<k; ++counter) {
if (fast == NULL)
return;
fast = fast->next;
}
}
};