LeetCode 2. 两数相加

题目

题目描述

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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
  • 题目数据保证列表表示的数字不含前导零

原题链接

题解

解题思路

  • 每个链表中的节点数在范围 [1, 100] 内,超出int或long的表示范围,故不能将链表转为数字相加。
  • 采取逐位相加,计算进位的方式:
    1. 声明一个链表用来存放相加后的结果。
    2. 不断地取两个链表的最低位,相加后加上进位(初值为0),判断是否需要进位,需要进位则更新进位信息。
    3. 进位判断完成后,用尾插法将该数字插入到链表中(头插法逆转元素顺序,尾插法顺序不变)。
    4. 某一个链表遍历完后,需要对另一个链表单独遍历,进行同样的操作。
    5. 两个链表都遍历完后,需要检验最后是否有进位,有进位则用尾插法将进位插入到链表中。
  • 算法笔记p253链表处理

代码实现(C)

typedef struct ListNode node;   // 表示声明的是一个结点
typedef struct ListNode List;   // 表示声明的是一个单链表

// 单链表向指定结点后插入结点
node *insert(node *pre, int value) {
    node *p = (node *) malloc(sizeof(node));
    p->val = value;
    node *r = pre->next;
    pre->next = p;
    p->next = r;
    return p;
}

List *head = NULL;      // 新建一个链表
node *tail = NULL;      // 尾指针
int carry = 0;          // 进位

// 计算进位和插入结点
void calculate(int sum) {
    carry = 0;                  // 进位已经加到sum中,置为0
    if (sum >= 10) {            // 如果可以产生进位
        carry = sum / 10;       // 更新进位
        sum %= 10;              // 取个位
    }
    tail = insert(tail, sum);   // 尾插法插入结点
}

struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
    head = (List *) malloc(sizeof(List));           // 初始化链表
    head->next = NULL;
    tail = head;                                    // 尾指针一开始指向头结点
    carry = 0;                                      // 初始化进位
    for (; l1 && l2; l1 = l1->next, l2 = l2->next)  // 计算l1和l2共同长度部分
        calculate(l1->val + l2->val + carry);
    for (; l1; l1 = l1->next)                       // 计算l1剩余部分
        calculate(l1->val + carry);
    for (; l2; l2 = l2->next)                       // 计算l2剩余部分
        calculate(l2->val + carry);
    if (carry != 0)                                 // 如果处理完l1和l2所以位数,还有进位
        tail = insert(tail, carry);                 // 尾插法插入进位
    return head->next;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值