使用归并排序算法排序链表 java
(图源leecodfe,侵删)
递归版:将链表不断的找中点二分到一个节点后,开始向上排序合并。 (1对1比较,合并 -----> 2对2比较,合并…)
迭代版:先计算长度,再从步长为1开始(每次翻倍),先切分两次,再将切分的两个部 分进行排序,不断循环,最后合并…
纯记录,后面的代码不上注释
递归版:
class Solution { public ListNode sortList(ListNode head) { return split(head); } private ListNode split(ListNode head) { if(head==null || head.next==null) return head; ListNode fast=head,slow=head; while(fast.next!=null && fast.next.next!=null){ slow=slow.next; fast=fast.next.next; } ListNode mid=slow; ListNode rightHead=mid.next; mid.next=null; ListNode left=split(head); ListNode right=split(rightHead); return merge(left,right); } private ListNode merge(ListNode left, ListNode right) { ListNode t=new ListNode(0); ListNode res=t; ListNode t1=left,t2=right; while (t1!=null && t2!=null){ if(t1.val<t2.val){ t.next=t1; t1=t1.next; }else{ t.next=t2; t2=t2.next; } t=t.next; } if(t1!=null) t.next=t1; else if(t2!=null) t.next=t2; return res.next; } }
时间复杂度:O(n log n) 空间复杂度:O(log n)
迭代版:
class Solution { public ListNode sortList(ListNode head) { if(head==null || head.next==null) return head; int len=getLength(head); ListNode dummy= new ListNode(0,head); for (int i = 1; i < len; i<<=1) { ListNode pre=dummy; ListNode cur=pre.next; while (cur!=null){ ListNode l1=cur; ListNode l2=split(l1,i); cur=split(l2,i); ListNode temp=merge(l1,l2); pre.next=temp; while (pre.next!=null){ pre=pre.next; } } } return dummy.next; } private ListNode merge(ListNode l1, ListNode l2) { ListNode dummy=new ListNode(0); ListNode res=dummy; while (l1!=null && l2!=null){ if(l1.val<l2.val){ dummy.next=l1; l1=l1.next; }else{ dummy.next=l2; l2=l2.next; } dummy=dummy.next; } if(l1!=null) dummy.next=l1; else if(l2!=null) dummy.next=l2; return res.next; } private ListNode split(ListNode head, int step) { if(head==null) return null; while (head.next!=null && --step>0){ head=head.next; } ListNode right=head.next; head.next=null; return right; } private int getLength(ListNode head) { int count=0; while (head!=null){ count++; head=head.next; } return count; } }
时间复杂度:O(n log n) 空间复杂度:O(1)