【困难】25. K 个一组翻转链表
struct ListNode【singly-linked list】
/**
* 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) {}
* };
*/
图2-5 单链表结构
单链表的结点结构
typeded struct node{//结构名为node
T Element;//元素域Element 用户自定义的元素类型T
struct node* Link;//指针域Link
}Node;//单链表的结点类型Node
std::pair class template
https://www.cplusplus.com/reference/utility/pair/?kw=pair
pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail) {}
pair<ListNode*, ListNode*> result = myReverse(head, tail);
Pair of values
This class couples together a pair of values, which may be of different types (T1 and T2). The individual values can be accessed through its public members first and second.
Pairs are a particular case of tuple.
std::tie function template
https://www.cplusplus.com/reference/tuple/tie/?kw=tie
tie(head, tail) = myReverse(head, tail);
Tie arguments to tuple elements
Constructs a tuple object whose elements are references to the arguments in args, in the same order.
This allows a set of objects to act as a tuple, which is especially useful to unpack tuple objects.
The special constant ignore can be used to specify elements of a tuple to be ignored instead of tied to a specific object.
25. K 个一组翻转链表
https://leetcode-cn.com/problems/reverse-nodes-in-k-group/
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗? 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
/**
* 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:
ListNode* reverseKGroup(ListNode* head, int k) {
}
};
模拟
/**
* 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*> myReverse(ListNode* head, ListNode* tail) {
ListNode* prev = tail->next;
ListNode* p = head;
while (prev != tail) {
ListNode* nex = p->next;
p->next = prev;
prev = p;
p = nex;
}
return {tail, head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* hair = new ListNode(0);//新建一个节点
hair->next = head;//,把它接到链表的头部,
ListNode* pre = hair;//让它作为 pre 的初始值,这样 head 前面就有了一个节点,就可以避开链表头部的边界条件。
while (head) {
ListNode* tail = pre;
// 查看剩余部分长度是否大于等于 k
for (int i = 0; i < k; ++i) {//对于每个分组,我们先判断它的长度是否大于等于 k。
tail = tail->next;
if (!tail) {
return hair->next;//否则不需要翻转。
}
}
//若是,我们就翻转这部分链表,
ListNode* nex = tail->next;
// 这里是 C++17 的写法,也可以写成
// pair<ListNode*, ListNode*> result = myReverse(head, tail);
// head = result.first;
// tail = result.second;
tie(head, tail) = myReverse(head, tail);
// 把子链表重新接回原链表
pre->next = head;
tail->next = nex;//将子链表的头部与上一个子链表连接,
pre = tail;
head = tail->next;//以及子链表的尾部与下一个子链表连接。
}
return hair->next;//只要返回它的下一个节点就好了。
}
};
边做边写 参考力扣官方题解和《数据结构:C语言描述(第3版)》