NC50_链表中的结点每k个一组翻转
知识点:链表
题目链接
题目描述
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
要求空间复杂度O(1)
例如:
给定的链表是1→2→3→4→5
对于 k=2, 你应该返回=2→1→4→3→5
对于 k=3, 你应该返回=3→2→1→4→5
示例1
输入:{1,2,3,4,5},2
输出:{2,1,4,3,5}
解题思路
方法一:
- 定义一个哨兵结点 插入链表的头部
- 分段 的使用头插法 将链表反序 pre作为每一小段链表的头结点 并负责连接 注意反序的过程
- 每个子序列反序后,pre和cur需要更新到下一个子序列
pre cur nex
-1 -> 1 -> 2 -> 3 -> 4 -> 5 k=2
pre nex cur
-1 -> 2 -> 1 -> 3 -> 4 -> 5 k=2
pre cur nex
-1 -> 2 -> 1 -> 3 -> 4 -> 5 k=2
方法二:
- 采用递归的方式,定义一个翻转函数,每次翻转k个结点 也就是翻转x到x+k-1的结点
- 函数递归跳出的条件: 结点为空 或者 结点的后面也是空的 或者剩下的长度小于k
- 如何连接 保存原来的头结点 和 尾结点 原来的头结点是新链的尾结点 现在的尾结点是下一个需要翻转的开始
head tail
1 -> 2 -> 3 -> 4 -> 5 k=2
newhead head tail
2 -> 1 -> 3 -> 4 -> 5 k=2
head tail
2 -> 1 -> 3 -> 4 -> 5 k=2
代码
#include "cheader.h"
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x):val(x){}
};
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(head==nullptr || head->next == nullptr || k < 2)
return head;
ListNode* newhead = new ListNode(-1);
newhead->next = head;
ListNode* pre = newhead;
ListNode* cur = head;
ListNode* nex = nullptr;
int length = 0;
while(head!=nullptr) {
length++;
head = head->next;
}
for(int i = 0; i < length/k;i++) {
for(int j = 1; j < k; j++) {
nex = cur->next;
cur->next = nex->next;
nex->next = pre->next; // 注意 不是nex->next = cur
pre->next = nex;
}
pre = cur;
cur = cur->next;
}
return newhead->next;
}
};
class Solution2 {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(head == nullptr || head->next == nullptr)
return head;
ListNode *tail = head;
for (int i = 0; i < k; i++) {
if (tail == nullptr) {
return head;
}
tail = tail->next;
}
ListNode* newhead = reverse(head, tail);
//下一轮的开始的地方就是tail
head->next = reverseKGroup(tail, k);
return newhead;
}
ListNode* reverse(ListNode* head,ListNode *tail){
ListNode* pre = nullptr;
ListNode* nex;
while(head != tail){
nex = head->next;
head->next = pre;
pre = head;
head = nex;
}
return pre;
}
};
int main()
{
ListNode* head = new ListNode(1);
ListNode* node2 = new ListNode(2);
ListNode* node3 = new ListNode(3);
ListNode* node4 = new ListNode(4);
ListNode* node5 = new ListNode(5);
head->next = node2;node2->next = node3;node3->next = node4;node4->next = node5;
Solution2 s;
ListNode* newhead = s.reverseKGroup(head, 2);
while(newhead != nullptr){
cout<<newhead->val<<endl;
newhead = newhead->next;
}
return 0;
}