【困难】25-K 个一组翻转链表 Reverse Nodes in k Group
题目
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解法
方法一:逐段翻转
解题思路
首先明确反转链表的算法:
那么对于k个一组的翻转链表问题,如果链表长度为n,那就是n/k个子问题,而对于每个子问题的初始化:
- res是前一个子问题最后的curr/初始化
- head和curr是前一个子问题的end
- end是head后的第k个节点
- next是curr的next,record是next的next
所以只要重复子问题的解决过程即可(先判断是否有k个节点可以翻转,也就是end是否存在),要注意的是,每次完成子问题之后,还要把他与前面的子问题k串连起来,也就是前一个问题的head与后一个问题最终的curr相连,返回的结果就是第一个k串最终的头
代码
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(head == NULL or head->next == NULL) return head;
ListNode *result = new ListNode(0), *res = result, *curr = head, *end = head;
res->next = head;
while(curr){
ListNode *subhead = curr;
ListNode *next = curr->next;
for(int i = 0; i < k; ++i){ // if end exists
if(end != NULL) end = end->next;
else return result->next;
}
for(int i = 0; i < k-1; ++i){
end = next->next;
next->next = curr;
curr = next;
next = end;
}
subhead->next = end;
res->next = curr;
res = subhead;
curr = end;
}
return result->next;
}
};
方法二:栈
解题思路
每k个节点放入栈,弹出来后自然就是翻转的了,只是要注意如果不够k个的时候,需要把正序的第一个与已有的最后一个相连
代码
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
stack<ListNode*> s;
ListNode* res = new ListNode(0), *curr = head, *end = res;
while(true){
int count = 0;
ListNode *start = curr;
for(count=0; count<k; ++count){
if(!curr) break;
s.push(curr);
curr = curr->next;
}
if(count != k){
end->next = start;
break;
}
while(!s.empty()){
ListNode * temp = s.top();
end->next = temp;
end = end->next;
s.pop();
}
}
return res->next;
}
};
Email:1252418308@qq.com