2.两数相加
var addTwoNumbers = function(l1, l2) {
let head = null, tail = null;
let carry = 0;
while(l1 || l2){
// 判断l1(l2)是否存在,若不为空,则n1(n2)为l1.val(l2.val)
const n1 = l1 ? l1.val : 0;
const n2 = l2 ? l2.val : 0;
// 该节点的值为当前节点l1.val + l2.val,和进位值的和
const sum = n1 + n2 + carry;
if(!head){
// new ListNode创造一个新的节点
// 如果没有head,则将当前节点值放在head = tail = 新创的节点上
head = tail = new ListNode(sum % 10);
}else{
// 如果有head,则将当前节点值加在tail下一个节点上
tail.next = new ListNode(sum % 10);
// tail指向下一个节点
tail = tail.next;
}
// 进位值
carry = Math.floor(sum / 10);
// l1和l2都指向下一个节点
if(l1){
l1 = l1.next;
}
if(l2){
l2 = l2.next;
}
}
// 如果还有carry未处理,则加在tail最后面
if(carry > 0){
tail.next = new ListNode(carry);
}
// head一直指向头节点,因为需要记得这个首地址
// tail去处理,将每个节点连接在head后面,tail将不再指向首地址
// 因为head首地址 = tail首地址,所以直接返回head
return head;
};
19.删除链表的倒数第 N 个结点
方法一:添加哨兵节点dummy,指向head
var removeNthFromEnd = function(head, n) {
// 创建一个哨兵节点,指向头节点
let dummy = new ListNode(0);
dummy.next = head;
// 计算链表长度,创建一个新的链表tail去记录,以免破坏head
let len = 0;
let tail = head;
while(tail){
len++;
tail = tail.next;
}
// 找到需要删除的节点的前一个节点
len = len - n;
// 这一句的含义:tail.next = head;
tail = dummy;
while(len > 0){
len--;
tail = tail.next;
}
// 跳出while,代表len = 0,意味着下一个节点被删除
tail.next = tail.next.next
// dummy用来记录链表首地址,tail去遍历处理链表
return dummy.next;
};
方法二:不添加哨兵节点,直接用head处理
注意:需要特别处理删除头节点的情况,因为如果删除的是头节点,不能简单地返回修改后的
head
var removeNthFromEnd = function(head, n) {
let len = 0;
let current = head;
// 计算链表长度
while (current) {
len++;
current = current.next;
}
// 找到需要删除的节点的前一个节点
let m = len - n;
// 如果要删除的是头节点,返回head.next
if (m === 0) {
return head.next;
}
current = head;
// 移动到需要删除节点的前一个节点
for (let i = 1; i < m; i++) {
current = current.next;
}
// 删除节点
current.next = current.next.next;
// 返回修改后的头节点
return head;
};