(免责声明:上学)
据我所知,递归拆分链表,然后将其发送到另一个要合并的函数是O(nlogn)时间和O(n)空间。是否可以在链表上进行合并,具有O(nlogn)时间和O(1)空间复杂度?你会怎么做呢?
获得任何帮助
PS:为了确保传统的mergesort是空间复杂度0(n),这是0(n)的一个例子,对吧?如何改变O(1)空间?
void sortTrack() {
Node merge = this.head;
this.head = Node (merge);
}
public Node mergeSort(Node head){
if ((head == null)||(head.next == null)){
return head;
}
Node left = head;
Node right = head.next;
while((right != null) && right.next != null){
head = head.next;
right = right.next.next;
}
right = head.next;
head.next = null;
return merge(mergeSort(left), mergeSort(right));
}
public Node merge(Node left, Node right){
Node head = new Node ();
Node temp = head;
while((left != null) && (right !=null)){
if(left <= right ){
temp.next = left;
temp = left;
left = left.next;
}
else{
temp.next = right;
temp = right;
right = right.next;
}
}
if(right == null)
temp.next = left;
else
temp.next = right;
return head.next;
}
答案 0 :(得分:2)
您的递归方法需要Θ(log n )额外空间,因为当您一路走来时,您将在堆栈上调用Θ(log n )下来合并排序单例列表。
要将其减少到O(1)额外空间,您需要从递归的“自上而下”方法进行更改,在此方法中将列表拆分为两个大的子列表,对它们进行排序,并合并结果 - 为您提供Θ(log n )的递归深度 - 到迭代的“自下而上”方法,您首先对所有单例列表进行排序,然后对所有对进行排序(第一个)和第二个元素,然后是第三个和第四个,等等,然后是所有四重奏(第一到第四个元素,然后是第五到第八个等) - 给你Θ(log n )< em>传递列表。每次传递都需要Θ( n )时间,因此总时间仍为Θ( n log n )。
总的来说,你将有三种方法:
Node merge(Node listA, Node listB)
,您已经写过。
Node mergePass(Node list, int i)
:
merge
,然后”粘贴“结果;然后对节点#(2 n +1)到#(3 n )和节点#(3 n +1)执行相同的操作#(4 名词的);等 Node mergeSort(Node list)
:
mergePass(..., 1)
。mergePass(..., 2)
,然后在 结果等上调用mergePass(..., 4)
,每次加倍i
。i
是列表的长度(或更大)之前停止,因为如果mergePass(..., i)
那么大,i
是无操作。