题目
Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3 Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0 Output: -1->0->3->4->5
十分钟思考
对于nlogn的时间复杂度,必定采用递归,折半,分而治之的思想。从list中间劈开,然后递归分割,排序后逐次合并。
但是写代码,不知道具体怎么写,看了其他人的实现,思路是对的,自己尝试写一遍。尤其是从中间分割list的方法,利用快慢指针,很厉害。一定要学会这个方法,之前判断单链表是否有环,也是利用快慢指针。来,自己写一下。代码一次通过,没有一点问题。总结一下:
1,拆分list的方法,利用快慢指针
2 合并两个单链表,从小到大排序。首先建立一个dummy node,作为新链表的开头,然后一个新的curr指针,指向加入的node
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
//分而治之,从中间分开list
//基准条件
if(head==null||head.next==null){
return head;
}
ListNode fast=head;
ListNode slow=head;
ListNode pre=slow;
while(fast!=null&&fast.next!=null){
//记录断开位置
pre=slow;
slow=slow.next;
fast=fast.next.next;
}
//断开list
pre.next=null;
//递归拆分
ListNode nodeLeft=sortList(head);
ListNode nodeRight=sortList(slow);
//合并list,需要依次拼接,刚开始各有一个节点,然后会有多个,依次往上合并
return merge(nodeLeft,nodeRight);
}
private ListNode merge(ListNode l1,ListNode l2){
//一个dummynode,一个curr指针,依次比较添加到新链表,长度不同,剩下的加入就可以
ListNode dummy=new ListNode(0);
ListNode curr;
curr=dummy;
while(l1!=null&&l2!=null){
if(l1.val<l2.val){
curr.next=l1;
l1=l1.next;
}
else{
curr.next=l2;
l2=l2.next;
}
curr=curr.next;
}
//如果长度不一样
if(l1!=null){
curr.next=l1;
}
if(l2!=null){
curr.next=l2;
}
return dummy.next;
}
}