【leetcode】25. Reverse Nodes in k-Group
题目说明
https://leetcode-cn.com/problems/reverse-nodes-in-k-group/description/
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
解法1
首先遍历链表,记录结点个数,当满足个数等于k时,开始进行反转,反转完成后,个数重新计数。
假设n为k区间中需要反转的第一个结点,n+k为最后一个结点。使用pre指向[n,n+k]区间的前一个结点(即n-1),使用cur进行遍历,满足条件时,cur指向n+k这个结点
反转方法:对[n,n+k]进行遍历,每次将后一个结点指向前一个结点。[n,n+k]这个区间进行反转操作后,还需要使[n,n+k]这个区间的结点能够与两边串联起来:将pre指向n+k这个结点,并且n这个结点需要指向n+k+1这个结点。
/*
* 时间复杂度:O(n)
*/
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode *dummy = new ListNode(0);
dummy->next = head;
ListNode *pre = dummy;
ListNode *pre_in = NULL; //[n,n+k]区间操作时的前结点
ListNode *cur = NULL; //遍历整个结点
ListNode *cur_in = NULL; //[n,n+k]区间操作时的当前结点
ListNode *next = NULL; //[n,n+k]区间操作时的下一结点
ListNode *first = NULL; //记录n这个结点
int count = 0;
cur = pre->next;
while(cur){
count ++;
if (count == k){
pre_in = pre;
cur_in = pre->next;
first = cur_in;
for (int i = 0; i < k; i ++){//反转操作
next = cur_in->next;
cur_in->next = pre_in;
pre_in = cur_in;
cur_in = next;
}
pre->next = pre_in; //pre指向n+k这个结点
first->next = next; //n这个结点需要指向n+k+1这个结点
pre = first; //移动pre结点到n结点,是为下一个k长度区间的前一个结点
cur = pre->next;
count = 0; //重新计数
continue;
}
cur = cur->next;
}
return dummy->next;
}
解法2
两次遍历,第一次得到链表长度。
第二次遍历每次进行k区间的反转。
反转的方法:
假设[n,n+k]这个区间进行反转,对第i(n<=i<=n+k)个结点进行反转时将n+i指向i-1,n-1指向i,n指向i+1,而其他点不需要变动
/*
* 时间复杂度:O(n)
*/
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode *dummy = new ListNode(0);
dummy->next = head;
ListNode *pre = dummy;
ListNode *cur = pre->next;
ListNode *next = NULL;
int num = 0;
while(cur){
cur = cur->next;
num ++;
}
while(num >= k){
cur = pre->next;
next = cur->next;
for (int i = 1; i < k; i ++){
cur->next = next->next;
next->next = pre->next;
pre->next = next;
next = cur->next;
}
num -= k;
pre = cur;
}
return dummy->next;
}