题解 | #牛群的重新分组#
牛群的重新分组
https://www.nowcoder.com/practice/267c0deb9a6a41e4bdeb1b2addc64c93
题目考察的知识点
链表的基本操作。能熟练掌握链表的操作。
题目分析
这道题大概可以概括为:给定k值,k个一组翻转链表,如若剩余数量不足k个则原样输出。
特殊情况:
- 当k=5,即链表长度时,就转化为了反转链表。
- 注意空链表和单元素链表的处理,因为题目备注有规定k值的范围所以不需要担心大于长度小于长度这些七七八八的。
大概流程:
指针变量有四个:cur和pre都是反转链表时常用的指针,分别代表前一个指针和当前指针,start和final指针是下一组起点和尾节点,用于翻转后的位置确认和每组之间的链表连接,后面根据分组数num循环来操作待反转的链表分组,注意当循环组数达到最后一组的时候,final尾节点就应该是start节点,因为3->4在翻转后4->3,3这个start指针位置就是final尾节点位置。这里需要加个if判断一下。
其它的细节请看代码块注释,很详细了。
编程语言和代码展示
编程语言c++,代码展示如下:
/** * struct ListNode { * int val; * struct ListNode *next; * ListNode(int x) : val(x), next(nullptr) {} * }; */ #include <iostream> class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param head ListNode类 * @param k int整型 * @return ListNode类 */ ListNode* reverseSwap(ListNode* head, int k) { ListNode* cur = head; ListNode* pre = nullptr; ListNode* temp = nullptr; while (k) { temp = cur->next;//记住下个节点方便步进 cur->next = pre;//后面节点指向前面 pre = cur; cur = temp; k--; } return pre;//返回反转后的最后一个节点 } ListNode* reverseKGroup(ListNode* head, int k) { // write code here //题目宗旨:k节点一组翻转 //注意点1 如果节点数不是k的整数倍 则剩余节点保持原有顺序 //注意点2 空或者1个节点返回原head if (head == nullptr || head->next == nullptr)return head; //注意点2 ListNode* cur = head; ListNode* pre = head; ListNode* start = cur; ListNode* final = nullptr; int count = 0;//长度 int num = 0;//组数 int i = k;//循环变量 等于k 因为k不能变 用于循环控制 while (cur != nullptr) { count++; cur = cur->next; } cur = head;//用cur遍历之后一定要重置指向为head if(count == k){//说明整个链表为一组翻转==反转链表 return cur=reverseSwap(head,k); } num = count / k; bool hflag = false;//用于控制头节点获取首次翻转后的分组头节点控制锁变量 while (num) {//要进行反转的组数 i = k;//循环变量重置 while (i) { start = start->next; i--; }//start保存下一个待反转数组的入口地址 final = start;//开始寻找下一组的尾节点 if (num != 1) { i = k - 1; while (i) { final = final->next; i--; } } cur = reverseSwap(cur, k); //2 if (hflag == false) { head = cur;//连接反转后的链表分组 hflag = true; } pre->next = final;//当前分组首节点指向下一组尾节点 pre = start; cur = start;//cur步进为最新的待反转分组入口 num--; } return head; } };#题解#