赞
踩
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表: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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题说难也难,说简单也不为过,只要保证在链表翻转的过程中链表不会断开。总能找到正确的结果,好了。不废话了,直接看基本思想
基本思想:
核心思想:递归
这道题可以分解成两步递归:
好了,基本思想是这样,下面来看每一部分的递归如何实现 :
/** * 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* sp,*ep,*p=head,*new_h,*pre=new ListNode(0),*ppre=new ListNode(0); if(head==NULL||k<=0) return NULL; while(p!=NULL){ sp=p;//该组的起始节点 int i=0; while(i<k-1&&p->next!=NULL){ p=p->next; ++i; } ep=p;//该组的终止节点 p=p->next;//记录下一组的起始节点 pre=ppre;//上一组k个节点的开始节点 ppre=sp;//该次k个节点的开始节点 if(i==k-1){//翻转K个节点 if(sp==head) new_h=ep; //初始调用时,其前驱结点是该组节点翻转前的最后一个节点的下一个节点(1->2->3->4->5,k=2,翻转3->4后,应当传递的前驱结点是5,目的是在翻转后和后面未翻转的节点连接上) invert(sp,ep->next,k); //逆转完后需要和上一次逆转结果连接上 if(sp!=head){//第一组不需要和之前的组连接 pre->next=ep;//上一组的最后一个节点和该组翻转之前的最后一个节点进行连接 } } else{//不足k个,保持原序 if(sp==head) new_h=head; break; } } return new_h; } private: void invert(ListNode* head,ListNode* pre,int k){ if(k==1){ head->next=pre; return; } invert(head->next,head,k-1); head->next=pre; } };
执行结果:通过
显示详情
执行用时 :24 ms, 在所有 cpp 提交中击败了79.05%的用户
内存消耗 :9.9 MB, 在所有 cpp 提交中击败了74.23%的用户
能否将翻转整个链表的过程转化为递归的形式呢?
当然可以,看如下代码:
/** * 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(head==NULL||k<0) return NULL; //查验该节点后面是否有k个节点 ListNode *sp,*ep,*p; int i=0; p=head; sp=p; while(i<k-1&&p->next!=NULL){ p=p->next; ++i; } ep=p; //不足k个节点,递归终止条件 ListNode* post; if(i!=k-1){ return sp;//不进行翻转,直接返回起始节点 } //递归 //整体翻转 ep->next=reverseKGroup(ep->next,k); //局部翻转 invert(sp,ep->next,k); return ep; } private: void invert(ListNode* head,ListNode* pre,int k){ if(k==0){ return; } invert(head->next,head,k-1); head->next=pre; } };
不得不承认递归时间效率低,但是写起来代码,比非递归形式容易,因为递归的过程省去了很多链表连接的步骤
执行结果:通过
显示详情
执行用时 :28 ms, 在所有 cpp 提交中击败了46.04%的用户
内存消耗 :9.7 MB, 在所有 cpp 提交中击败了86.00%的用户
非递归
采用非递归的思想来翻转链表,这道题虽然是自己做的,但是调试了好半天才AC,而且自己的思路还比较麻烦,后来看到公众号上一篇文章发现链表还是面试中会涉及到的手撕代码的知识点,于是乎,参考了评论区最热的思想,写出了如下代码。
参考:评论区
基本思想:
/** * 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(head==NULL||k<=0) return NULL; ListNode *dummy=new ListNode(0),*p=head,*pre; dummy->next=head;//dummy便于处理头节点 pre=dummy;//pre指向上一组的最后一个节点 while(p){ //找到从p开始的k个节点 int i=0; ListNode* sNode=p,*eNode; while(p->next!=NULL && i<k-1){ p=p->next; ++i; }//循环完后p指向该组的第k个节点 eNode=p; p=p->next;//p指向下一组的第一个节点 eNode->next=NULL;//设置这个节点的目的是为了知道这一组节点的结束的节点 //判断是否能构成一组节点 if(i==k-1){ pre->next=reverse(sNode); pre=sNode; } else{ pre->next=sNode; break; } } return dummy->next; } private: ListNode* reverse(ListNode* head){ ListNode* p=head,*pre=NULL,*next; while(p){ next=p->next; p->next=pre; pre=p; p=next; } return pre; } };
执行结果:通过
显示详情
执行用时 :24 ms, 在所有 cpp 提交中击败了78.75%的用户
内存消耗 :9.6 MB, 在所有 cpp 提交中击败了96.16%的用户
二刷
/** * 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(head == NULL || k < 2) return head; ListNode *p = head, *st = p, *next; int cnt = 0; while(p && cnt < k - 1){ cnt++; p = p->next; } if(p){ next = p->next; ListNode *temp = reverseKGroup(next, k); p->next = NULL; ListNode *nhead = NULL; reverseKNode(st, nhead); st->next = temp; head = nhead; } return head; } private: void reverseKNode(ListNode * head, ListNode * &pre){ if(head == NULL) return; ListNode * next = head->next; head->next = pre; pre = head; head = next; reverseKNode(head, pre); } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。