[leetcode][list] Reverse Nodes in k-Group

来源:互联网 发布:蛙泳世界纪录 知乎 编辑:程序博客网 时间:2024/06/05 05:26

题目:

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For 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


/** * 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 (NULL == head || NULL == head->next || k <= 1) return head;ListNode *pGroupFirst = NULL;//指向反转后K元组的第一个节点ListNode *pGroupLast = NULL;//指向反转后K元组的最后一个节点//只有最后一组可能不足k个字符,isNotLastGroup作为循环结束标志bool isNotLastGroup = reverseK(head, k, pGroupFirst, pGroupLast);//反转第一个k元组ListNode *headNew = pGroupFirst;//指向新链表的第一个节点ListNode *pLast = pGroupLast;//指向当前新链表的最后一个节点ListNode *pCur = pGroupLast->next;//指向当前节点while (isNotLastGroup && pCur){//还没到最后一组且当前节点不为空isNotLastGroup = reverseK(pCur, k, pGroupFirst, pGroupLast);//反转kpLast->next = pGroupFirst;//连入原链表pLast = pGroupLast;//K元组最后一个节点就是新链表最后一个节点pCur = pGroupLast->next;//当前节点变为K元组的下一个节点}return headNew;}private://若从start开始存在K个节点,则反转从start开始的k个节点,first指向反转后的第一个节点,last指向反转后的最后一个节点;若不足k个节点,则不反转, 返回值表示链表是否反转过了。//由于只遍历链表链表一次,所以在事先并不知道是否足够k个节点,所以在反转过程中若发现不足k个节点,再通过调用自己反转回来,由于反转了两次,效果就像没反转过一样。使用这种方法,只有不足K个节点的元组(只有最后一组)需要遍历两次。bool reverseK(ListNode *start, int k, ListNode *&first, ListNode *&last){//注意:无论什么情况,都应根据情况对first和last赋以合适的值if (NULL == start) {//当前链表为空,置first和last为空first = last = NULL;return false;}if (NULL == start->next){//当前链表只有一个节点,first和last都指向该节点first = last = start;return false;}if (1 == k){ //k==1说明不用任何反转,first和start指向同一个节点,遍历链表使last指向最后一个节点first = start;while (start){last = start;start = start->next;}return false;}ListNode *pCur = start->next ;ListNode *pNext = start->next->next;int cnt = 1;first = last = start;//first和last都初始化为startlast->next = NULL;//last->next初始化为NULL,遍历K个节点后再使其指向K元组的下一个节点(足够k个节点)while (cnt < k && pCur){ListNode *pNext = pCur->next;//暂存pCur的下一个节点pCur->next = first;//pCur连入新链表first = pCur;//更新新链表第一个节点pCur = pNext;//更新当前节点为原pCur的下一个节点++cnt;//节点计数器加1}if (cnt == k){last->next = pCur;//pCur指向K元组的下一个节点return true;}else{//不足k个节点,再反转回来reverseK(first, cnt, first, last);//last->next = NULL,和last的初值相等,所以不必再赋值return false;}}};

简化代码:

/** * 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 (NULL == head || NULL == head->next || k <= 1) return head;ListNode *p = head->next, *headNew = head;head->next = NULL;//head成为最后一个节点int i = 1;while (i < k && NULL != p){//翻转前k个节点ListNode *q = p->next;//将当前节点加入处理后链表成为新headNewp->next = headNew;headNew = p;p = q;++i;}if (i == k) head->next = reverseKGroup(p, k);//递归翻转后面的部分。注headNew肯定不为NULLelse{//剩余节点个数少于k,再翻转回去,注意此时要以剩余节点个数为kheadNew = reverseKGroup(headNew, i);}return headNew;}};



0 0
原创粉丝点击