链表中的节点每k个一组翻转
这道题给定一个链表和一个整数k,每隔k个节点一组翻转链表。[1,2,3,4,5],k=2,翻转过后的链表为[2,1,4,3,5]。最后剩下不足k个节点则不动。
- 解题思路:做过了指定区间翻转链表那道题,这道题还是能想出来的,就是找到待翻转的起始节点curr,然后开始翻转k个节点。最主要的是判断剩下节点数量是否大于k,我们使用first指向目前待翻转区间起始节点,last指向末尾节点。首先判断是否还存在长度为k的区间,如果长度小于k则停止翻转,翻转了[first,last]之后,我们再修改first和last指向下一次待翻转的区间,直到剩下的节点数量小于k。
代码
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
void reverse(ListNode* pre,ListNode* curr,ListNode* &last, int n){
//从指定节点开始反转n-1个
//这个n代表k,因为是从first开始翻转,所以只翻转first后面的n-1个节点
//使用头插法将curr后面的节点依次插入到pre后面来
ListNode* next=nullptr;
for(int i=0;i<n-1;i++){
next=curr->next;
curr->next=next->next;
next->next=pre->next;
pre->next=next;
}
last=curr;//因为我们要通过last节点来指定下一个区间的pre和first节点,所以last节点应该指向翻转后区间的最后一个节点,因此我们使用引用来将last指向翻转结束后的curr节点
}
ListNode* reverseKGroup(ListNode* head, int k) {
// write code here
//每k个反转一次
//类似指定区间反转链表
ListNode* temp=new ListNode(-1);
temp->next=head;
ListNode* first=head,*last=temp;
ListNode* pre=temp;
//先让last指向区间末尾节点,如果不存在k个节点则直接返回
for(int i=0;i<k;i++){
last=last->next;
if(last==nullptr){
return temp->next;
}
}
while(last){
reverse(pre,first,last,k);
pre=last;
first=last->next;
if(!first){
return temp->next;
}
for(int i=0;i<k;i++){
last=last->next;
if(last==nullptr){
return temp->next;
}
}
}
return temp->next;
}
};