当前位置:   article > 正文

[力扣Hot 100------第2题--148.排序链表]_给定两个排序列表l1和l2,计算l1 l2的最快算法具有时间复杂性(nlogn)。

给定两个排序列表l1和l2,计算l1 l2的最快算法具有时间复杂性(nlogn)。

归并排序(递归法)
题目要求时间空间复杂度分别为O(nlogn)O(nlogn)和O(1)O(1),根据时间复杂度我们自然想到二分法,从而联想到归并排序;

数组做归并排序的空间复杂度为 O(n)O(n),分别由新开辟数组O(n)O(n)和递归函数调用O(logn)O(logn)组成,而根据链表特性:

数组额外空间:链表可以通过修改引用来更改节点顺序,无需像数组一样开辟额外空间;
递归额外空间:递归调用函数将带来O(logn)O(logn)的空间复杂度,因此若希望达到O(1)O(1)空间复杂度,则不能使用递归。
通过递归实现链表归并排序,有以下两个环节:

分割 cut 环节: 找到当前链表中点,并从中点将链表断开(以便在下次递归 cut 时,链表片段拥有正确边界);
我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
找到中点 slow 后,执行 slow.next = None 将链表切断。
递归分割时,输入当前链表左端点 head 和中心节点 slow 的下一个节点 tmp(因为链表是从 slow 切断的)。
cut 递归终止条件: 当head.next == None时,说明只有一个节点了,直接返回此节点。
合并 merge 环节: 将两个排序链表合并,转化为一个排序链表。
双指针法合并,建立辅助ListNode h 作为头部。
设置两指针 left, right 分别指向两链表头部,比较两指针处节点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表。
返回辅助ListNode h 作为头部的下个节点 h.next。
时间复杂度 O(l + r),l, r 分别代表两个链表长度。
当题目输入的 head == None 时,直接返回None。

  1. var sortList = function(head) {
  2. if(head===null) return null;
  3. if(head.next===null) return head;
  4. var fast=head.next,slow=head;
  5. while(fast!==null&&fast.next!==null){
  6. fast=fast.next.next;
  7. slow=slow.next;
  8. }
  9. var temp=slow.next;
  10. slow.next=null;
  11. var left=sortList(head);
  12. var right=sortList(temp);
  13. var h=new ListNode(0);
  14. var res=h;
  15. while(left!==null&&right!==null){
  16. if(left.val<=right.val){
  17. h.next=left;
  18. left=left.next;
  19. }else{
  20. h.next=right;
  21. right=right.next;
  22. }
  23. h=h.next;
  24. }
  25. if(left!==null) h.next=left;
  26. if(right!==null) h.next=right;
  27. return res.next;
  28. };

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/506300
推荐阅读
相关标签
  

闽ICP备14008679号