题目描述:
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
分析:
题意:给定一个单链表,对于每k个的结点,反转它们的顺序(最后不足k个结点的部分保持原序),并返回结果。
思路:这道题是LeetCode 24的进化版本,同样考察头插法(之前有说明,头插法逆序,尾插法正序)。为了方便操作,我们用指针h建立一个空结点(方便指针s的操作,同时保存最终结果)。这里跟LeetCode 24的区别:我们不能用一个flag来处理,假设单链表包含n个结点,则总共需要反转的有T=[n/k]个段,剩余部分保持原序。对于每个段,我们用period变量来统计当前处理结点的位置,如果period等于k,则当前段处理完毕、period清零,此时指针s指向下一段结点的开始位置。
时间复杂度为O(n)。
代码:
#include <bits/stdc++.h>
using namespace std;
struct ListNode{
int val;
ListNode *next;
ListNode(int x): val(x), next(NULL){}
};
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
// Exceptional Case:
if(!head || !head->next){
return head;
}
ListNode * p = head, *r;
ListNode *h = new ListNode(-1), *s = h;
int n = 0;
while(p){
n++;
p = p->next;
}
p = head;
int T = n / k, period = 0, cnt = 0;
// debug
// cout << "n: " << n << ", T: " << T << endl;
if(T == 0){
return head;
}
// every k nodes: head insert method
while(p){
period++;
r = p;
p = p->next;
r->next = s->next;
s->next = r;
if(period == k){
for(int i = 1; i <= k; i++){
s = s->next;
}
period = 0;
cnt++;
if(cnt == T){
break;
}
}
}
s->next = p;
return h->next;
}
};