我有一个关于这个链表合并代码如何工作的快速问题



我对head.next如何返回整个列表而不是下面代码中的下一个值(如l1、l2、dummy.next(感到困惑。特别是我想知道head.next是如何返回整个排序数组并跳过第二行输入的-1值的。

let mergeTwoLists = function (l1, l2) {
let dummy = new ListNode(-1);
let head = dummy;
while (l1 !== null && l2 !== null) {
if (l1.val <= l2.val) {
dummy.next = l1;
l1 = l1.next;
} else {
dummy.next = l2;
l2 = l2.next;
}
dummy = dummy.next;
}
if (l1 !== null) {
dummy.next = l1;
} else {
dummy.next = l2;
}
return head.next;
};
class ListNode {
constructor(val = null, next = null) {
this.val = val;
this.next = next;
}
}

也许这有助于可视化列表的构建方式:

让输入是一个值为[3,9]的列表,另一个值仅为[4]的列表:

l1
↓
3 → 9 → null
l2
↓
4 → null

在循环开始之前,将创建一个新节点:

head
↓
-1
↑
dummy

循环将进行第一次迭代,并且if条件为true。第一个dummmy.next被适配,这导致了这种情况:

head l1
↓   ↓
-1 → 3 → 9 → null
↑
dummy    
l2
↓
4 → null

然后CCD_ 3被重新分配一个新的参考:

head     l1
↓       ↓
-1 → 3 → 9 → null
↑
dummy    
l2
↓
4 → null

循环中的最后一条语句为dummy:分配了一个新的引用

head     l1
↓       ↓
-1 → 3 → 9 → null
↑
dummy    
l2
↓
4 → null

循环第二次迭代,if条件现在为false,因此我们进入else块。首先对dummmy.next进行了调整(这打破了它与l1的联系,因此我移动了l1l2的可视化(:

head     l2
↓       ↓
-1 → 3 → 4 → null
↑
dummy    
l1
↓
9 → null

然后l1被重新分配一个新的参考,在这种情况下,它变成null:

head          l2
↓            ↓
-1 → 3 → 4 → null
↑
dummy    
l1
↓
9 → null

循环中的最后一条语句为dummy:分配了一个新的引用

head          l2
↓            ↓
-1 → 3 → 4 → null
↑
dummy    
l1
↓
9 → null

在此阶段,循环条件不再为真(l2null(,因此执行循环之后的if块。这将dummy.next与剩余(而非null(引用链接起来。同样,为了可视化,我交换了l1l2:的位置

head         l1
↓           ↓
-1 → 3 → 4 → 9 → null
↑
dummy    
l2
↓
null

现在我们来看最后一句话:return head.next。请注意,head从未离开在开始时创建的新节点。

所以返回的参考是:

head         l1
↓           ↓
-1 → 3 → 4 → 9 → null
↑
returned    
l2
↓
null

请注意head在整个函数执行过程中是如何一直指向带-1的节点的。值为-1的临时节点将被垃圾回收,因为一旦函数返回(head本地变量(,就没有变量再引用它了。

最新更新