LeetCode - 2 两数相加

题目来源

2. 两数相加 - 力扣(LeetCode)

题目描述

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

题目解析

本题我的解题思路是:

首先:判断出 l1 和 l2 两个链表哪个长,我们以较长的链表作为基础,即将较短的链表合并入较长的链表中,避免创建新链表。

比较两个链表长短的策略:

  • 首先:定义两个指针 ll1 和 ll2 分别指向 l1 和 l2。
  • 然后:ll1 和 ll2 同步next移动,直到一方为 null 时停止。
  • 最后:检查 ll1 和 ll2 谁为 null,谁就较短。

为了代码简单,我们可以总是保证 l1 是较长链表(如果 l1 是较短的,则互换 l1 和 l2)。

之后:就是同步遍历 l1 和 l2,将 l2 对应位值 加入 l1 对应位值中

  • 由于 l1 是较长的,因此同步遍历过程中,l2 可能变为 null,因此我们需要注意判空,即当 l2 为 null 时,l1 对应位值 += 0。
  • 合并后,检查 l1 每位的值,若对应值 >= 10,则需要进位,以及取余。

C源码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
    // 比较两个链表的长度
    struct ListNode *ll1 = l1;
    struct ListNode *ll2 = l2;

    // 同步遍历
    while (ll1 != NULL && ll2 != NULL) {
        ll1 = ll1->next;
        ll2 = ll2->next;
    }

    // 如果ll1先遍历完,则l1更短,为了代码简单,我们这里保证l1总是指向较长的链表
    if (ll1 == NULL) {
        struct ListNode *tmp = l1;
        l1 = l2;
        l2 = tmp;
    }

    // l3记录结果
    struct ListNode *l3 = l1;

    // 逐位相加
    while (l1 != NULL) {
        // 将较短链表对应位值 合并入 较长链表对应位值 中
        l1->val += (l2 != NULL ? l2->val : 0);

        // 进位、取余
        if (l1->val >= 10) {
            if (l1->next == NULL) {
                l1->next = malloc(sizeof(struct ListNode));
                l1->next->val = 0;
                l1->next->next = NULL;
            }

            l1->next->val += l1->val / 10; // 进位
            l1->val %= 10; // 取余
        }

        // 继续遍历
        l1 = l1->next;

        if (l2 != NULL) {
            l2 = l2->next;
        }

    }

    return l3;
}

C++源码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        // 比较两个链表的长度
        ListNode* ll1 = l1;
        ListNode* ll2 = l2;

        // 同步遍历
        while (ll1 != nullptr && ll2 != nullptr) {
            ll1 = ll1->next;
            ll2 = ll2->next;
        }

        // 如果ll1先遍历完,则l1更短,为了代码简单,我们这里保证l1总是指向较长的链表
        if (ll1 == nullptr) {
            ListNode* tmp = l1;
            l1 = l2;
            l2 = tmp;
        }

        // l3记录结果
        ListNode* l3 = l1;

        // 逐位相加
        while (l1 != nullptr) {
            // 将较短链表对应位值 合并入 较长链表对应位值 中
            l1->val += l2 != nullptr ? l2->val : 0;

            // 进位、取余
            if (l1->val >= 10) {
                if (l1->next == nullptr) {
                    l1->next = new ListNode(0);
                }

                l1->next->val += l1->val / 10; // 进位
                l1->val %= 10;                 // 取余
            }

            // 继续遍历
            l1 = l1->next;

            if (l2 != nullptr) {
                l2 = l2->next;
            }
        }

        return l3;
    }
};

Java源码实现

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode() {}
 * ListNode(int val) { this.val = val; }
 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        // 比较两个链表的长度
        ListNode ll1 = l1;
        ListNode ll2 = l2;

        // 同步遍历
        while (ll1 != null && ll2 != null) {
            ll1 = ll1.next;
            ll2 = ll2.next;
        }

        // 如果ll1先遍历完,则l1更短,为了代码简单,我们这里保证l1总是指向较长的链表
        if (ll1 == null) {
            ListNode tmp = l1;
            l1 = l2;
            l2 = tmp;
        }

        // l3记录结果
        ListNode l3 = l1;

        // 逐位相加
        while (l1 != null) {
            // 将较短链表对应位值 合并入 较长链表对应位值 中
            l1.val += (l2 != null ? l2.val : 0);

            // 进位、取余
            if (l1.val >= 10) {
                if (l1.next == null)
                    l1.next = new ListNode(0);

                l1.next.val += l1.val / 10; // 进位
                l1.val %= 10; // 取余
            }

            // 继续遍历
            l1 = l1.next;

            if (l2 != null) {
                l2 = l2.next;
            }

        }

        return l3;
    }
}

Python源码实现

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        # 比较两个链表的长度
        ll1 = l1
        ll2 = l2

        # 同步遍历
        while ll1 and ll2:
            ll1 = ll1.next
            ll2 = ll2.next

        # 如果ll1先遍历完,则l1更短,为了代码简单,我们这里保证l1总是指向较长的链表
        if ll1 is None:
            l1, l2 = l2, l1

        # l3记录结果
        l3 = l1

        # 逐位相加
        while l1:
            # 将较短链表对应位值 合并入 较长链表对应位值 中
            l1.val += (l2.val if l2 else 0)

            # 进位、取余
            if l1.val >= 10:
                if l1.next is None:
                    l1.next = ListNode(0)

                l1.next.val += l1.val // 10  # 进位
                l1.val %= 10  # 取余

            # 继续遍历
            l1 = l1.next

            if l2:
                l2 = l2.next

        return l3

JavaScript源码实现

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function (l1, l2) {
    // 比较两个链表的长度
    let ll1 = l1;
    let ll2 = l2;

    // 同步遍历
    while (ll1 != null && ll2 != null) {
        ll1 = ll1.next;
        ll2 = ll2.next;
    }

    // 如果ll1先遍历完,则l1更短,为了代码简单,我们这里保证l1总是指向较长的链表
    if (ll1 == null) {
        const tmp = l1;
        l1 = l2;
        l2 = tmp;
    }

    // l3记录结果
    const l3 = l1;

    // 逐位相加
    while (l1 != null) {
        // 将较短链表对应位值 合并入 较长链表对应位值 中
        l1.val += l2 != null ? l2.val : 0;

        // 进位、取余
        if (l1.val >= 10) {
            if (l1.next == null) l1.next = new ListNode(0);

            l1.next.val += parseInt(l1.val / 10); // 进位
            l1.val %= 10; // 取余
        }

        // 继续遍历
        l1 = l1.next;
        if (l2 != null) l2 = l2.next;
    }

    return l3;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员阿甘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值