题目链接
题目大意
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解题思路
这里的思路是把整个链表分成 K 个结点一组的小链表,然后依次翻转每个小链表,再将这些小链表连起来就是答案。
为了实现这个目标,首先需要一个翻转链表的函数 reverse(),函数返回翻转后的链表,这个是比较简单的。
接下来,我们要把原始链表分成 K 个结点一组的小链表去翻转。
这里用 cnt 计数,ans 为最终翻转后的链表的头指针,p 为最终翻转后的链表的尾指针,temp 指向当前小链表的头结点,head 指向当前结点。
当 cnt+1 == K 时,说明从 temp 至 head 总共有 K 个结点,这个时候应该把这个小链表拿出来翻转一下然后接到 p 的后面。用 end 指向当前 head 指向的结点。令 end = NULL,就把小链表从原始链表上拿下来了。p->next = reverse(temp) 就把翻转后的小链表接到了当前已经翻转的链表的后面。再用一个 while 循环,把 p 更新为当前已经翻转的链表的尾指针。接下来开始找下一个小链表,首先更新 head = head->next,因为 temp 存储的是下一个小链表的头结点,所以要令 temp = head,这样又回到了初始状态,所以要 continue 跳过本次循环后面的内容;当 cnt + 1 ≠ K 时,head = head->next 即可。
最后还应有 p->next = temp,因为当最后一组结点没有 K 个时,是不会翻转的,但 temp 仍指向最后一组结点的头结点,直接把 temp 接到 p 后面即可。
参考代码如下:
class Solution {
public:
ListNode* reverse(ListNode* head) {
ListNode* ans = NULL;
while(head) {
ListNode* next = head->next;
head->next = ans;
ans = head;
head = next;
}
return ans;
}
ListNode* reverseKGroup(ListNode* head, int k) {
int cnt = 0;
ListNode* ans = new ListNode(0);
ListNode* temp = head, *p = ans;
while(head) {
cnt++;
if(cnt == k) {
cnt = 0;
ListNode* end = head;
head = head->next;
end->next = NULL;
p->next = reverse(temp);
while(p->next)
p = p->next;
temp = head;
continue;
}
head = head->next;
}
p->next = temp;
return ans->next;
}
};
解题感悟
这题周末想了好久都没搞出来,今天状态好,一会儿就做出来了,看来状态好的时候效率真的会很高呀,以后要尽量在状态好的时候做一些有难度的事情。
加油。