25-K个一组翻转链表
@Author:CSU张扬
@Email:csuzhangyang@gmail.com or csuzhangyang@qq.com
Category | Difficulty | Pass rate | Tags | Companies |
---|---|---|---|---|
algorithms | Medium | 72.20% | linked-list | facebook / microsoft |
1. 题目
给你一个链表,每 个节点一组进行翻转,请你返回翻转后的链表。
是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
2.解法
2.1 解法一:递归解法
总的来说,这道题就是多次反转链表。
1. 如何反转链表?
- 我们需要三个指针
pre, cur, next
,分别指向前一个结点、当前结点、后一个结点。 - 注意:当
cur
指向第一个结点时,我们要令pre = nullptr
。 - 我们先保存好下一个节点:
next = cur->next
。再反转当前结点和前一个结点:cur->next = pre
。然后pre, h
都向后移一次:pre = h; h = next
。 - 需要反转几个结点即循环几次。
2. 递归返回值和如何使用返回值?
- 应该返回反转之后的头结点(也就是反转之前的尾结点),这里就是
pre
。 - 令反转之后的尾结点(也就是反转之前的头结点)指向下一次递归的返回值(也就是下一次递归的反转后的头结点)。
3. 递归什么时候结束?
当剩余结点数不足 个时,我们的递归函数要先检查结点数有没有 个。
执行用时: 20 ms, 在所有 cpp 提交中击败了97.34%的用户
内存消耗: 9.5 MB, 在所有 cpp 提交中击败了98.88%的用户
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* temp = head;
for (auto i = 0; i < k; ++ i) {
if (temp == nullptr) {
return head;
}
temp = temp->next;
}
ListNode* h = head;
ListNode* pre = nullptr;
for (auto i = 0; i < k; ++ i) {
ListNode* next = h->next;
h->next = pre;
pre = h;
h = next;
}
head->next = reverseKGroup(h, k);
return pre;
}
};