【Hot 100 刷题计划】 LeetCode 148. 排序链表 | C++ 归并排序自顶向下
LeetCode 148. 排序链表 题目描述题目级别中等给你链表的头结点head请将其按升序排列并返回排序后的链表。进阶你可以在O(NlogN)O(N \log N)O(NlogN)时间复杂度和常数级空间复杂度下对链表进行排序吗示例 1:输入head [4,2,1,3]输出[1,2,3,4] 破题思路归并排序 (Divide and Conquer)要在O(NlogN)O(N \log N)O(NlogN)时间内完成排序常见的算法有快速排序、堆排序和归并排序。但在链表这种数据结构中**归并排序Merge Sort**是绝对的王者。因为它可以在合并阶段直接通过修改指针来实现不需要像数组那样开辟大量的临时拷贝空间。本解法采用了**自顶向下Top-down**的递归归并排序核心分为两大步1. 分Divide快慢指针找中点利用经典的快慢指针法把链表从中间一分为二。⚠️ 极客避坑点找中点时fast指针必须初始化为head-next如果fast初始化为head在处理只有 2 个节点的链表时slow会走到第 2 个节点。此时从中点断开左边依然是 2 个节点会导致递归陷入死循环最终爆栈。让fast先走一步可以确保在偶数节点时slow准确停在左半部分的最后一个节点。2. 合Merge双指针合并有序链表这部分逻辑完全等同于经典的题目《21. 合并两个有序链表》。创建一个虚拟头节点dummy然后比较左右两半链表的当前节点谁小谁就接在dummy的后面最后将剩余的尾巴接上即可。 C 代码实现 (原汁原味作者版)classSolution{public:ListNode*sortList(ListNode*head){// 递归终止条件如果链表为空或只有一个节点天然是有序的直接返回if(!head||!head-next){returnhead;}// 1. 快慢指针找中点ListNode*slowhead;// 重点细节fast 先走一步防止偶数节点时划分死循环ListNode*fasthead-next;while(fastfast-next){slowslow-next;fastfast-next-next;}// 2. 将链表从 slow 处断开分为 [head, slow] 和 [slow-next, 尾] 两部分ListNode*secondslow-next;slow-nextnullptr;ListNode*firsthead;// 3. 对左右两半分别进行深度优先递归排序firstsortList(first);secondsortList(second);// 4. 将两个排序好的单链表合并returnmergeList(first,second);}// 辅助函数合并两个有序链表ListNode*mergeList(ListNode*left,ListNode*right){ListNode*dummynewListNode(0);ListNode*curdummy;while(leftright){if(left-valright-val){cur-nextleft;leftleft-next;}else{cur-nextright;rightright-next;}curcur-next;}// 把未遍历完的剩余部分直接挂在末尾if(left)cur-nextleft;elsecur-nextright;returndummy-next;}};
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2564712.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!