链表的两种两数相加|刷题打卡

135 阅读3分钟

每日算法 -- 链表

  • 这是两道十分相似的链表求和题,都是给定两个以链表形式的数字,求和后返回一个用链表表示的和
  • 第一题是反向的,即链表表头是个位数,如数字 123,在链表中表示为 3-2-1
  • 第二题是正向的,即链表表头是最高位,如数字 123,在链表中表示为 1-2-3
  • 不同的排序主要会影响到进位的时候的处理。

面试题 02.05. 链表求和

面试题 02.05. 链表求和

分析

  1. 需要考虑两个链表都存在的时候进位,也要考虑有一条链表跑完后的处理
  2. 需要注意末位进一的情况
// 面试题 02.05. 链表求和
// https://leetcode-cn.com/problems/sum-lists-lcci/
/**
 * @分析
 * 1. 传入传出都是链表,当然可以转成数组等,处理完再换回来,但是这样就没意思了。
 * 
 * @注意
 * 1. 个位在首字母
 */
var addTwoNumbers = function (l1, l2) {
    let emptyNode = current = new ListNode()
    let addNum = 0 // 是否需要进位
    while (l1 && l2) {
        let temp = l1.val + l2.val + addNum
        if (temp >= 10) {
            temp %= 10
            addNum = 1
        } else {
            addNum = 0
        }
        current.next = new ListNode(temp)
        current = current.next
        l1 = l1.next
        l2 = l2.next
    }
    let l3 = l1 || l2 //剩下的那个链表
    while (addNum) {
        // 如果还有进位,那么必须处理到每位为止
        if (!l3) {
            // l1,l2 已经结束
            current.next = new ListNode(1)
            return emptyNode.next
        }
        let temp = l3.val + addNum
        if (temp >= 10) {
            temp %= 10
            addNum = 1
        } else {
            addNum = 0
        }
        current.next = new ListNode(temp)
        current = current.next
        l3 = l3.next
    }
    // 当有一个走完了,剩下的直接全部拼接起来就可以了
    current.next = l3
    return emptyNode.next
};

两数相加2

两数相加2

分析

  1. 同样是两个链表表示的数相加,但是这里是正向的
  2. 所以一开始的时候长的那个链表是可以直接获取到的
  3. 等两个链表都合一的时候,再做进位处理。
  4. 由于这边进位是从后往前走的,所以如果一开始就用链表存储,当存在进位的时候,就需要往前推,要不用双指针链表,要不只能用数组存储,最后在变换,这里直接用数组即可.
// 两数相加2
// https://leetcode-cn.com/problems/add-two-numbers-ii/
/**
 * @分析
 * 1. 同样是两个链表表示的数相加,但是这里是正向的
 * 2. 所以一开始的时候长的那个链表是可以直接获取到的
 * 3. 等两个链表都合一的时候,再做进位处理。
 * 4. 由于这边进位是从后往前走的,所以如果一开始就用链表存储,当存在进位的时候,就需要往前推,要不用双指针链表,要不只能用数组存储,最后在变换,这里直接用数组即可
 */
var addTwoNumbers = function (l1, l2) {
    let l1_1 = l1, l2_2 = l2 // 因为需要快慢指针求得多出来那一段
    const res = []
    let emptyNode = current = new ListNode()
    while (l1_1 && l2_2) {
        l1_1 = l1_1.next
        l2_2 = l2_2.next
    }
    while (l1_1) {
        // l1 比较长,正式开始前可以先走 l1
        res.push(l1.val)
        l1 = l1.next
        l1_1 = l1_1.next
    }
    while (l2_2) {
        // l2 比较长,正式开始前可以先走 l2
        res.push(l2.val)
        l2 = l2.next
        l2_2 = l2_2.next
    }
    // 这个时候 l1,l2 已经一样长了
    let addNum = 0
    while (l1 && l2) {
        let temp = l1.val + l2.val 
        if (temp >= 10) {
            temp %= 10
            addNum = 1
        } else {
            addNum = 0
        }
        let index = res.length - 1 // 求的是上一个下标
        while (addNum && index>=0) {
            res[index] += 1
            if (res[index] >= 10) {
                res[index] = 0
                addNum = 1
            } else {
                addNum = 0  // 如果没有,那么循环也就结束了
            }
            
            index--
        }
        if(addNum){
            // 证明遍历完了 res,还有 addNum,所以需要在前面 +1 了
            res.unshift(1)
        }
        res.push(temp)
        l1 = l1.next
        l2 = l2.next
    }
    // 走完了
     res.reduce((prev,cur) =>{
        prev.next =new ListNode(cur)
        prev = prev.next
        return prev
    },current)
    return emptyNode.next
}

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情