我最近在学习链表,被困在LeetCode No.2。我知道链表可以有一个没有任何数据的头,但有一个指向列表中包含数据的第一个节点的引用(链接(。在这种情况下,l1和l2似乎都没有这种头部?此外,方法返回head.next而不是head,这是否意味着结果也是一个没有这种head的列表?那么,在哪种情况下,我们应该使用上面提到的带有标题的列表?
解决方案如下:
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int carry = 0;
ListNode head = new ListNode(0), p = head;
while (l1 != null || l2 != null || carry != 0) {
int sum = carry;
if (l1 != null) { sum += l1.val; l1 = l1.next; }
if (l2 != null) { sum += l2.val; l2 = l2.next; }
p.next = new ListNode(sum % 10);
p = p.next;
carry = sum / 10;
}
return head.next;
}
}
我知道链表可以有一个没有任何数据的头,但有一个指向列表中包含数据的第一个节点的引用(链接(。
这实际上不是存储链表的正常方式。";没有任何数据的头";可能会产生误导,因为尚不清楚此节点是否没有数据。如果您返回这样一个列表,Leet Code不会将第一个节点与其他节点区别对待:它的数据将被认为是相关的。
似乎l1和l2都没有这种头脑?
没错。
这是否意味着结果也是一个没有这种头的列表?
是的,这正是Leet Code所期望的。
那么在哪种情况下,我们应该使用上面提到的带有标题的列表?
使用它不是绝对的要求,但它使代码更容易一些。它是一个临时的伪节点,在结束时不会返回。
以下是当您不创建额外节点时代码的外观:
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int carry = 0;
ListNode head = null, p = null;
while (l1 != null || l2 != null || carry != 0) {
int sum = carry;
if (l1 != null) { sum += l1.val; l1 = l1.next; }
if (l2 != null) { sum += l2.val; l2 = l2.next; }
ListNode node = new ListNode(sum % 10);
if (head == null) {
head = node;
} else {
p.next = node;
}
p = node;
carry = sum / 10;
}
return head;
}
}
请注意,现在循环的主体必须检查它是哪种情况:这是第一个节点吗?那么head
必须引用它。否则,上一个节点的next
属性必须引用它,遗憾的是,在每次迭代中都会执行此检查,而实际上只需要第一次。虚拟节点的使用使得这是不必要的。