Algorithm 为什么空间复杂度为O(n)的算法比复杂度为O(1)的算法使用更少的内存?

Algorithm 为什么空间复杂度为O(n)的算法比复杂度为O(1)的算法使用更少的内存?,algorithm,space-complexity,Algorithm,Space Complexity,问题涉及: 给您两个非空链表,表示两个非负整数。这些数字以相反的顺序存储,它们的每个节点都包含一个数字。将两个数字相加,并以链表形式返回总和 Input: l1 = [2,4,3], l2 = [5,6,4] Output: [7,0,8] Explanation: 342 + 465 = 807. 我比较了以下两种解决方案: 空间复杂度为O(1)的算法 它使用了超过39000kb的内存: 空间复杂度为O(n)的算法 而且它使用的内存小于39000kb: 我很困惑。我在计算

问题涉及:

给您两个非空链表,表示两个非负整数。这些数字以相反的顺序存储,它们的每个节点都包含一个数字。将两个数字相加,并以链表形式返回总和

Input: l1 = [2,4,3], l2 = [5,6,4]      
Output: [7,0,8]  
Explanation: 342 + 465 = 807.
我比较了以下两种解决方案:

空间复杂度为O(1)的算法 它使用了超过39000kb的内存:

空间复杂度为O(n)的算法 而且它使用的内存小于39000kb:


我很困惑。我在计算空间复杂度时出错了吗?

您不应该太依赖这些内存使用情况报告。对于Java,有些方面不在您的控制之下,它们仍然会影响内存使用。例如,垃圾收集器自行决定何时将内存回收为空闲内存。此外,解析代码需要内存,并且不确定代码是否能够在专门用于运行程序的环境中运行。当然,测试代码也在相同的环境中运行。如果一些测试是随机的,以至于内存占用也依赖于它,那么这是另一个起作用的因素

您可能会发现,多次提交相同的代码会导致内存报告略有不同

在这些报告中,重要的是您的解决方案是否与其他高效解决方案的得分相对接近,并且不会占用50%以上的内存。在您的示例中,我们看到这些报告比较接近,差异不到1%。如果你把它们打印在一个X轴从0开始的图形上,你会注意到它们是多么的接近。该裕度可以忽略不计,并且在不同的运行中也会发生变化

至于算法:


一个使用O(1)辅助存储器,另一个使用O(1)辅助存储器,这是事实(你能同时提到这两种算法吗?这有助于分析。列表大小是多少?每个节点将占用大约12个字节,而你报告的是39MB,仅仅添加100个节点不会有任何区别。我会对leetcode的内存使用情况报告持保留态度。垃圾收集等方面可能会影响se统计数据,即使是相同的代码有时也会以不同的方式报告其内存使用情况。@trincot是的,我提交了这两个数据,得到了相反的结果。在问“为什么”之前首先确定它是真的…谢谢你这么多,你让我学到很多。我很抱歉这么晚才回复你。再次感谢。欢迎你。请考虑将这个解决方案标记为接受。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {   
    ListNode l1Pointer = l1;
    ListNode l2Pointer = l2;
    
    while(l1Pointer != null){
        if(l2Pointer != null)
            l1Pointer.val += l2Pointer.val;
        if(l1Pointer.val >= 10){
            l1Pointer.val -= 10;
            if(l1Pointer.next != null) l1Pointer.next.val++;
            else if(l2Pointer != null && l2Pointer.next != null) l2Pointer.next.val++;
            else l1Pointer.next = new ListNode(1);
        }
        if(l1Pointer.next == null && l2Pointer != null && l2Pointer.next != null){
            l1Pointer.next = l2Pointer.next;
            l2Pointer.next = null;
        }
        l1Pointer = l1Pointer.next;
        if(l2Pointer != null)
            l2Pointer = l2Pointer.next;
    }
    return l1;
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    ListNode c1 = l1;
    ListNode c2 = l2;
    ListNode sentinel = new ListNode(0);
    ListNode d = sentinel;
    int sum = 0;
    while (c1 != null || c2 != null) {
        sum /= 10;
        if (c1 != null) {
            sum += c1.val;
            c1 = c1.next;
        }
        if (c2 != null) {
            sum += c2.val;
            c2 = c2.next;
        }
        d.next = new ListNode(sum % 10);
        d = d.next;
    }
    if (sum / 10 == 1)
        d.next = new ListNode(1);
    return sentinel.next;
}