一. 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.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For 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
Difficulty:Hard
TIME:35MIN
解法一(遞歸)
很多鏈表問題都可以採用遞歸來求解,這道題也不例外。每次遞歸的過程中,都對鏈表的前k個結點進行反轉,如果小於k個結點,就不反轉鏈表。
ListNode* reverseKGroup(ListNode* head, int k) {
if(k <= 1)
return head;
ListNode *p = head;
int num = 0;
while(p != NULL && num != k) {
p = p->next;
num++;
}
if(num == k) {
p = reverseKGroup(p, k); //這裏的p指向的是第k+1個結點
while(num > 0) { //每次循環都將一個結點添加到p結點的前面
ListNode *cur = head->next;
head->next = p;
p = head;
head = cur;
num--;
}
head = p; //這裏的p指向的是第1個結點
}
return head;
}
代碼的時間複雜度爲
解法二(迭代)
和遞歸方法類似,不過通過一些額外的變量保存了一些狀態信息。
ListNode* reverseKGroup(ListNode* head, int k) {
if(k <= 1 || head == NULL)
return head;
ListNode *p = head;
ListNode *end = head; //指向k個結點已經反轉的尾結點(固定)
ListNode *nex = end->next; //指向k個結點已經反轉的尾節點的下一個結點
ListNode *result = new ListNode(-1);
result->next = head;
ListNode *pre = result; //指向k個結點已經反轉的首結點的前一個結點
int num = 0;
while(p != NULL) {
p = p->next;
num++;
}
while(num >= k) {
end = pre->next;
nex = end->next;
for(int i = 1; i < k; i++) { //反轉至少需要3個結點的參與
end->next = nex->next;
nex->next = pre->next;
pre->next = nex;
nex = end->next;
}
pre = end;
num -= k;
}
return result->next; //result一定會指向鏈表的首元素的前一個結點
}
代碼的時間複雜度爲