问题描述:
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
Example:
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
Note:
- Only constant extra memory is allowed.
- You may not alter the values in the list's nodes, only nodes itself may be changed.
解题思路:
题目给我们一个链表,和一个整数k,要求我们将链表分为每k个一组,颠倒组内顺序,组与组之间的顺序不变。
(要读好题!每个组的都要颠倒!)
并且要求我们空间复杂度为1,即不能使用额外的空间。这意味着我们需要用指针来解决这个问题(一般来讲,与链表有关的问题都可以首先考虑指针)
首先我们先找到一个组,可以用一个整数变量 i 来记录节点的个数,当 i % k == 0时,说明我们找到了一个组。
因为组与组之间的关系不会发生变化,所以我们需要两个指针分别指向组头和组尾,和另一个指针记录上一个组的结尾节点:
通过:
groupB->next = groupE->next;
lastE->next = groupE->next;
来将收尾颠倒,当然这个时候需要用局部变量记录改组的原开头和其指向的下一个节点,因为我们要改变原开头指向的下一个节点,记录他们不让他们丢失。
同时将组首尾指针移向下一个组的开头。
需要注意的是:因为这里我们移动了指针,所以我们要对计数器进行增一操作!!!!
然后可以开始组内颠倒了:
ListNode* temp = p->next;
p->next = prev;
prev = p;
p = temp;
代码:
/** * 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) { if(k < 2) return head; if(!head || !head->next) return head; ListNode* groupB = head; ListNode* groupE = head; ListNode* lastE = NULL; int i = 1; while(groupE && groupE->next){ groupE = groupE->next; i++; if(i % k == 0){ ListNode* p = groupB->next; ListNode* prev = groupB; if(i / k == 1){ head = groupE; } groupB->next = groupE->next; if(lastE){ lastE->next = groupE; } lastE = groupB; groupB = groupE->next; groupE = groupB; while(p != groupE){ ListNode* temp = p->next; p->next = prev; prev = p; p = temp; } i++; } } return head; } };