📟作者主页:慢热的陕西人
🌴专栏链接:力扣刷题日记
📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言
文章目录
- 牛客热题:单链表排序
- 题目链接
- 方法一:用数组排序再赋值回来
- 思路
- 代码
- 复杂度
- 方法二:归并排序
- 思路
- 代码
- 复杂度
牛客热题:单链表排序
题目链接
单链表的排序_牛客题霸_牛客网 (nowcoder.com)
方法一:用数组排序再赋值回来
思路
- 用数组先将链表中的值存储起来
- 对数组进行排序
- 将数组的值赋值给链表
代码
ListNode* sortInList(ListNode* head) {vector<int> v;ListNode* cur = head;while(cur != nullptr){v.push_back(cur->val);cur = cur->next;}sort(v.begin(), v.end());cur = head;for(auto & vv : v){cur->val = vv;cur = cur->next;}return head;}
复杂度
时间复杂度:O( N l o g N NlogN NlogN),用了c++原生的sort,底层是快排。
空间复杂度;O(N),借用了额外的数组空间
方法二:归并排序
思路
- 先将原先的链表,对半分开直到不能再分(单个节点的情况)
- 然后再将他们按照有序的方式合并
分开:
- 快慢指针的思路,快指针一步走两个节点,慢指针一步走一个节点
- 当快指针到达链表结尾的时候,那么这时候,慢指针恰好就在链表的中间位置
- 我们从这块将两个链表分开就好
合并:
- 创建一个哨兵位
- 遍历比较排序好的左右单链表区间
- 并逐个比较,尾插到哨兵位
代码
ListNode* sortInList(ListNode* head) {if(head == nullptr || head->next == nullptr) return head;//快慢指针寻找链表的中点ListNode* fast = head->next;ListNode* slow = head;while(fast != nullptr && fast->next != nullptr){slow = slow->next;fast = fast->next->next;}//将链表从中间分开ListNode* temp = slow->next;slow->next = nullptr;//递归左右两边进行排序ListNode* left = sortInList(head);ListNode* right = sortInList(temp);//创建新的链表,带有哨兵位ListNode* h = new ListNode(0);ListNode* res = h; //合并left和right两个链表while(left != nullptr && right != nullptr){if(left->val < right->val){h->next = left;left = left->next;}else {h->next = right;right = right->next;}h = h->next;}//最后查看left和right哪个还有剩余未添加的节点h->next = left == nullptr ? right : left;return res->next; }
复杂度
时间复杂度:O( N l o g N Nlog N NlogN),利用归并排序的思路实现。
空间复杂度:O(1),借用了常数个额外的空间。