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

标签 java mergesort space-complexity

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);

该函数的其余部分仅更改 next list1 指向的列表元素的成员和list2 .

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

将此函数与自上而下的递归方法或自下而上的迭代方法相结合,会产生一种具有 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;
}

关于java - Mergesort这个合并函数占用O(1)空间还是O(n)空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57447358/

相关文章:

java - 寻找大O递归

java - 从 forEach 循环内部传播异常

java - Gradle - 没有主要 list 属性

c++ - 主要跳过功能?

string - 句子中每个单词的反转字符

python - 时间复杂度与空间复杂度

java - Hibernate 是否将从数据库检索到的集合放入第一个 lvl 缓存?

java - 如何访问pdf中的超链接?

java - 如何将两个排序数组合并为一个排序数组?

Python3 - 合并排序实现