题目:给定一个链表,每次反转k个节点,返回修改后的链表。
k是一个正数,并且小于等于链表的长度;如果链表的长度不是k的整数倍,那么最后剩下的节点顺序不变。
要求空间复杂度O(1);
例子:1->2->3->4->5,k = 3,则返回 3->2->1->4->5;
这道题其实和它的上一道题,也就是 Swap Nodes in Pairs 如出一辙,k = 2时就是同一道题!那么我们当然也可以借鉴上一题的思路,只不过是把交换两个相邻节点的操作换成了反转k的节点的链表!不过需要注意如何处理最后不足k的节点的链表。
我们直接看代码:
鲁棒性:
- 由于题目里说了k是个正数,并且小于等于链表长度,那么我们自然会想到如果k不合法,那么要保证程序不能崩溃!
- head为nullptr时程序不能崩溃!
/**
* 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)
{
//注意这两种情况,k = 0的时候,我们下面的代码运行会出现问题
//而对于k = 1的情况,虽然下面的代码可以运行正确,但是考虑到效率问题,直接返回就好
if(k <= 0 || k == 1) return head;
ListNode phead = ListNode(0);
phead.next = head;
ListNode *ph = &phead;
//我们用ph来指向每一个需要反转的部分开头的前一个节点
ListNode *curr = head;
while(curr)
{
ListNode *h = curr;
for(int i = 0; i < k; ++i)
{
curr = curr->next;
//这里需要注意,如果curr为nullptr时i == k - 1
//则代表最后一个需要反转的部分的长度恰好等于k
//这个时候盲目返回结果会导致最后一部分没有被反转
if(!curr && i < k - 1) return phead.next;
//处理k大于链表长度的情况
if(!curr) break;
}
ListNode *l = curr;
//反转链表的h到l的部分(不包括l,反转后的链表末尾指向l)
//并且将前面已经反转过的链表与当前反转后的链表正确链接
ph->next = reverse(h, l);
ph = h;
}
return phead.next;
}
private:
ListNode* reverse(ListNode *s, ListNode *e)
{
ListNode *prev = e;
ListNode *curr = s;
while(curr != e)
{
ListNode *n = curr->next;
curr->next = prev;
prev = curr;
curr = n;
}
return prev;
}
};
下面是运行结果: