K个一组翻转链表
题目描述
给你一个链表,每k个节点一组进行翻转,请你返回翻转后的链表。
k是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是k的整数倍,那么请将最后剩余的节点保持原有顺序。
来源:力扣(LeetCode)
链接:k个一组翻转链表
测试样例分类
1.总结点个数不满k
2.总结点个数恰好为k的正整数倍
3.总结点个数为k的正整数倍加上remain(0<remain<k)
解题思路
按照测试样例的分类,可以对int型链表长度用/运算符得到有多少组。
- 对情况一:结果为0,无需翻转,直接返回头结点即可。
- 对情况二和三:结果为正整数,将每k个作为一组进行翻转,最后余下的不足k个的那一组直接取其头结点连接至最后的尾结点。
需要注意的点
在迭代法方式中,需要注意当前处理的组的头结点指针和尾结点指针,以及下一个组的头结点指针。
在递归方式中,需要将当前处理的组的头指针、当前组序号、总组数、k值作为参数传递。返回的是处理好的当前组的头结点指针。
代码&图解
状态图
迭代方式
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
//先求得链表的长度
int cnt = 0;
ListNode *cur = head;
while(cur){
++cnt;
cur = cur->next;
}
//若不足k个结点
if(cnt / k == 0){
return head;
}
//记录有多少组k个结点
int group = 0;
ListNode *dummy = new ListNode();
ListNode *rear = dummy;
cur = head;
while(group < cnt / k){
ListNode *new_rear = cur;
for(int i = 0;i < k;++i){
ListNode *cur_next = cur->next;
cur->next = rear->next;
rear->next = cur;
cur = cur_next;
}
rear = new_rear;
++group;
}
rear->next = cur;
return dummy->next;
}
};
递归方式
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
//遇到k个一组的最后一个结点时,则递归处理,处理内容为对接下来的k各结点翻转
//先求链表长度
int cnt = 0;
ListNode *cur = head;
while(cur){
++cnt;
cur = cur->next;
}
return reverseK(head,cnt/k,0,k);
}
//传入k个一组的首结点,k组的总组数,当前是第几组
//返回一个翻转好的k个一组的首结点
ListNode *reverseK(ListNode* head,int group_cnt,int group_cur,int k){
if(group_cur == group_cnt){
return head;
}
ListNode *rear = head;
ListNode *pre = NULL;
ListNode *cur = head;
for(int i = 0;i < k;++i){
ListNode *cur_next = cur->next;
cur->next = pre;
pre = cur;
cur = cur_next;
}
rear->next = reverseK(cur,group_cnt,group_cur+1,k);
return pre;
}
};
复杂度分析
时间复杂度:两种方式都为O(n)
空间复杂度:迭代方式为O(1),递归方式递归深度为(n/k)向下取整,故其空间复杂度为O(n/k)
欢迎大家转载本人的博客(需注明出处),本人另外还有一个个人博客网站:[https://www.lularible.cn],欢迎前去浏览。