Mergesort的这个合并函数占用O(1)空间还是O(n)空间?


private ListNode merge(ListNode list1, ListNode list2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
while (list1 != null && list2 != null) {
if (list1.val < list2.val) {
curr.next = list1;
list1 = list1.next;
} else {
curr.next = list2;
list2 = list2.next;
}
curr = curr.next;
}
if (list1 == null) {
curr.next = list2;
} else {
curr.next = list1;
}
return dummy.next;
}

在这里,我相信由于" curr"节点,它占用O(n(空间,因为curr节点将逐渐包含完整的链表。

这个merge函数使用O(1(空间。除了具有恒定大小的局部变量外,它只分配一个ListNodeListNode dummy = new ListNode(0);

函数的其余部分只是更改list1list2指向的列表元素的next成员。

可以通过编写初始测试来选择结果列表的初始节点来修改函数,甚至不分配单个额外的对象。

将此函数与自上而下的递归方法或自下而上的迭代方法相结合,会产生具有O(log(N(( 空间复杂度和 O(N.log(N((时间复杂度的排序算法。

要实现稳定排序,应将比较运算符更改为<=

这是一个没有任何分配的修改版本:

private ListNode merge(ListNode list1, ListNode list2) {
Listnode head, curr;
if (list1 == null)
return list2;
if (list2 == null)
return list1;
if (list1.val <= list2.val) {
curr = head = list1;
list1 = list1.next;
} else {
curr = head = list2;
list2 = list2.next;
}
while (list1 != null && list2 != null) {
if (list1.val <= list2.val) {
curr = curr.next = list1;
list1 = list1.next;
} else {
curr = curr.next = list2;
list2 = list2.next;
}
}
curr.next = (list1 != null) ? list1 : list2;
return head;
}

这是一个修改后的版本,在大多数情况下测试较少:

private ListNode merge(ListNode list1, ListNode list2) {
Listnode head, curr;
if (list1 == null)
return list2;
if (list2 == null)
return list1;
if (list1.val <= list2.val) {
curr = head = list1;
list1 = list1.next;
if (list1 == null) {
curr.next = list2;
return head;
}
} else {
curr = head = list2;
list2 = list2.next;
if (list2 == null) {
curr.next = list1;
return head;
}
}
for (;;) {
if (list1.val <= list2.val) {
curr = curr.next = list1;
list1 = list1.next;
if (list1 == null) {
curr.next = list2;
return head;
}
} else {
curr = curr.next = list2;
list2 = list2.next;
if (list2 == null) {
curr.next = list1;
return head;
}
}
}
}

在 C 或 C++ 中,可以更改原始代码以避免使用指针进行分配:

static ListNode *merge(ListNode *list1, ListNode *list2) {
ListNode *head = NULL;
ListNode **nextp = &head;
while (list1 && list2) {
if (list1->val <= list2->val) {
*nextp = list1;
nextp = &list1->next;
list1 = list1->next;
} else {
*nextp = list2;
nextp = &list2->next;
list2 = list2->next;
}
}
*nextp = list1 ? list1 : list2;
return head;
}

最新更新