目录
1.题目描述:
给你链表的头节点 head
,每 k
个节点一组进行翻转,请你返回修改后的链表。
k
是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k
的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 1:
输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]
示例 2:
输入:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5]
2.算法分析:
计算链表长度:
- 首先遍历整个链表,统计节点的总数
n
。这是为了知道有多少组k
个节点需要反转。
- 首先遍历整个链表,统计节点的总数
初始化辅助指针:
- 使用一个虚拟头节点
dummy
可以简化操作,尤其是在处理头节点的反转时。 p
用于记录当前待反转子链表的前一个节点。pre
和cur
用于反转子链表。
- 使用一个虚拟头节点
分组反转:
- 只要剩余的节点数
n
大于等于k
,就进行反转:- 反转连续的
k
个节点:- 使用类似反转单链表的方法,逐个反转节点。
- 调整连接:
- 将反转后的子链表与前面的部分连接起来。
- 将反转后的子链表的尾部与下一个子链表的头部连接。
- 移动
p
到下一个待反转子链表的前一个节点。
- 反转连续的
- 只要剩余的节点数
处理剩余节点:
- 如果剩余的节点数不足
k
,则不进行反转,直接保留原顺序。
- 如果剩余的节点数不足
返回结果:
- 由于
dummy
的next
始终指向链表的头节点,因此返回dummy->next
。
- 由于
示例
假设链表为 1 -> 2 -> 3 -> 4 -> 5
,k = 2
:
- 计算长度
n = 5
。 dummy -> 1 -> 2 -> 3 -> 4 -> 5
。- 第一组反转
1
和2
:- 反转后:
2 -> 1
,cur
指向3
。 - 调整连接:
dummy -> 2
,1 -> 3
。 p
移动到1
。
- 反转后:
- 第二组反转
3
和4
:- 反转后:
4 -> 3
,cur
指向5
。 - 调整连接:
1 -> 4
,3 -> 5
。 p
移动到3
。
- 反转后:
- 剩余
n = 1
,不足k
,不反转。 - 最终链表:
2 -> 1 -> 4 -> 3 -> 5
。
3.代码展示:
ListNode* reverseKGroup(ListNode* head, int k) {
int n = 0; // 代表节点的个数
// 计算出链表节点的个数
for (ListNode* cur = head; cur; cur = cur->next) {
n++;
}
// 创建一个空节点,便于后续的操作
ListNode* dummy = new ListNode(0, head);
ListNode* p = dummy;
ListNode* pre = nullptr;
ListNode* cur = head;
for (; n >= k; n-=k) {
for (int i = 0; i < k; i++) {
// 进行翻转操作
ListNode* nex = cur->next;
cur->next = pre;
pre = cur;
cur = nex;
}
if (p->next == nullptr) {
return 0;
}
ListNode* temp = p->next;
p->next->next = cur;
p->next = pre;
p = temp;
}
return dummy->next;
}
25. K 个一组翻转链表 - 力扣(LeetCode)https://leetcode.cn/problems/reverse-nodes-in-k-group/