leetcode链表-2.两数相加、19.删除链表的倒数第 N 个结点

70 阅读2分钟

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