怎么会这样做呢?自下而上的mergesort方式是否满足O(1)
额外空间要求?传统的mergesort是什么让它不是O(1)
空间?
这会是一种方式吗?
void mergeSort() {
ListNode merge = this.head;
this.head = mergeSort(merge);
}
ListNode mergeSort(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode slow = head; ListNode fast = head.next;
while(fast!=null && fast.next !=null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode left = head; ListNode right = slow.next;
slow.next = null;
left = mergeSort(left);
right = mergeSort(right);
return merge(left, right);
}
ListNode merge(ListNode L, ListNode R) {
if(L==null) return R;
if(R==null) return L;
ListNode h = null;
if(L.val <= R.val )){
h = L;
h.next = merge(L.next, R);
} else {
h = R;
h.next = merge(L, R.next);
}
return h;
}
答案 0 :(得分:2)
链接列表的自顶向下合并排序将消耗O(log(n))堆栈空间,并且由于扫描列表以分割它们,因此它比自下而上方法慢。由于递归merge(),问题中的示例代码将占用O(n)堆栈空间。
链表的自下而上合并排序使用一个小的(25到32)固定大小的节点引用(或指针)数组,这将满足O(1)空间要求。链接到wiki文章。如果感兴趣,我可以发布示例java代码。
https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation_using_lists
示例java代码:
// merge two already sorted lists
public ListNode merge(ListNode list0, ListNode list1) {
if(list0 == null)
return list1;
if(list1 == null)
return list0;
ListNode temp = new ListNode(0); // dummy node
ListNode dest = temp;
while(true){
if(list0.element <= list1.element){
dest.next = list0;
dest = list0;
list0 = list0.next;
if(list0 == null){
dest.next = list1;
break;
}
} else {
dest.next = list1;
dest = list1;
list1 = list1.next;
if(list1 == null){
dest.next = list0;
break;
}
}
}
return temp.next;
}
// sort list
public ListNode sort(ListNode head) {
final int NUMLIST = 32;
ListNode[] alist = new ListNode[NUMLIST];
ListNode node;
ListNode next;
int i;
// if < 2 nodes, return
if(head == null || head.next == null)
return;
node = head;
// merge node into array
while(node != null){
next = node.next;
node.next = null;
for(i = 0; (i < NUMLIST) && (alist[i] != null); i++){
node = merge(alist[i], node);
alist[i] = null;
}
if(i == NUMLIST) // don't go past end of array
i--;
alist[i] = node;
node = next;
}
// node == null
// merge array into single list
for(i = 0; i < NUMLIST; i++)
node = merge(alist[i], node);
return node;
}