题目要求时间复杂度为O(nlogn)并且空间复杂度为O(1):归并排序的时间复杂度合格,并且由于这是链表排序,因此,空间复杂度也可以做到O(1)。
关于归并排序,百度上有现成的代码,本题我采用的是递归的方式。不过这道题需要我们根据链表的特点做一些修改:例如,找中间节点的函数,需要使用快慢指针的方法,以完成高效的查找中间指针。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function(head) {// 归并排序的时间复杂度为O(nlogn)
if(head===null){
return head;
}
ret = mergeSort(head);
return ret;
function mergeSort(items){// 归并算法
if(items.next===null){
return items;
}
var left = items;
var right = getMid(items);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left,right){// 合并
var merge_result;
if(left===null){
return right;
}else if(right===null){
return left;
}
if(left.val<right.val){
lead = left;
left = left.next;
}else{
lead = right;
right = right.next;
}
var tmp = lead;
while(left!==null && right!==null){
if(left.val<right.val){
tmp.next = left;
tmp = left;
left = left.next;
}else{
tmp.next = right;
tmp = right;
right = right.next;
}
}
if(left!==null){
tmp.next = left;
}else{
tmp.next = right;
}
return lead;
}
function getMid(first){// 快慢指针获得中间点
//guaranteed that at least two nodes
var fast = first.next;
var slow = first.next;
var prev = first;
while(true)
{
if(fast !== null)
fast = fast.next;
else
break;
if(fast !== null)
fast = fast.next;
else
break;
prev = slow;
slow = slow.next;
}
prev.next = null; // cut
return slow;
}
};