25. K 个一组翻转链表
https://leetcode.cn/problems/reverse-nodes-in-k-group/description/
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
二:进行优化:
1.优化掉链表内部的倒置逻辑,不用循环,改成用迭代
2.优化掉pair数据的传递,改成用tie
3.简化逻辑,减少冗余的变量
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail, int k) {
// 把K个链表倒置
ListNode* cur=head,*pre=nullptr;
tail->next = nullptr;
while(cur){
ListNode *next = cur->next;
cur->next = pre;
pre = cur;
cur =next;
}
// 现在的tail就是新的head了
return {tail, head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(k==1) return head;
int cur_node_num = 0;
ListNode *p = head, *tmp_tail, *new_head, *tmp_head = head,
*old_tail = nullptr;
// p用来遍历节点
// tmp_tail用来记录当前尾巴
// new_head 记录下一个头
// tmp_head 记录当前头 tmp_head到tmp_tail是K个节点
// ans记录所有的头
ListNode* ans = nullptr;
while (p) {
cur_node_num += 1;
if (cur_node_num % k == 0) {
// 找到了五个连续的节点
new_head = p->next;
//
tie(tmp_head,tmp_tail) = reverseK(tmp_head, p, k);
if (!old_tail) {
// 第一组转置,会更新掉头节点
ans = tmp_head;
} else {
old_tail->next = tmp_head;
}
old_tail = tmp_tail;
tmp_tail->next = new_head;
// 完成修改后
p = old_tail->next;
tmp_head = p;
} else {
p = p->next;
}
}
if (cur_node_num % k != 0) {
// 剩下的按原有顺序
old_tail->next = tmp_head;
}
return ans;
}
};
一:暴力解法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail, int k) {
// 把K个链表倒置
ListNode* ans = tail;
tail->next = nullptr;
for (int i = 0; i < k - 1; i++) {
ListNode *p = head, *pre;
while (p && p->next) {
pre = p;
p = p->next;
}
// 每次都找到最后一个节点,挂到tail上面
tail->next = p;
tail = tail->next;
// 要从原来的链上删除掉这个节点
pre->next = nullptr;
}
tail->next = head;
tail = tail->next;
// 现在的tail就是新的head了
return {ans, tail};
}
ListNode* reverseKGroup(ListNode* head, int k) {
int cur_node_num = 0;
ListNode *p = head, *tmp_tail, *new_head, *tmp_head = head,
*old_tail = nullptr;
// p用来遍历节点
// tmp_tail用来记录当前尾巴
// new_head 记录下一个头
// tmp_head 记录当前头 tmp_head到tmp_tail是K个节点
// ans记录所有的头
ListNode* ans = nullptr;
while (p) {
cur_node_num += 1;
if (cur_node_num % k == 0) {
// 找到了五个连续的节点
tmp_tail = p;
new_head = p->next;
//
pair<ListNode*, ListNode*> t = reverseK(tmp_head, tmp_tail, k);
ListNode *f_h = t.first, *f_t = t.second;
if (!old_tail) {
// 第一组转置,会更新掉头节点
ans = f_h;
} else {
old_tail->next = f_h;
}
old_tail = f_t;
f_t->next = new_head;
// 完成修改后
p = old_tail->next;
tmp_head = p;
} else {
p = p->next;
}
}
if (cur_node_num % k != 0) {
// 剩下的按原有顺序
old_tail->next = tmp_head;
}
return ans;
}
};