(图源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)