LeetCode刷题笔记:2. 两数相加

273 阅读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
  • 题目数据保证列表表示的数字不含前导零

链表结构如下:

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

解题思路

题目将10进制整数用链表进行表示,每一位存储在一个节点中,往表头的方向为低位,往表尾的方向为高位。

由于10进制整数的每一位只能是0~9之间的整数,因此我们可以判断每两个节点之和最多不超过18,即如果两个数的同位相加产生了进位,只有可能是进1;同时产生进位的情况下,剩下的低位数字最大为8,此时如果更低一位的数字也产生了进位,那么最大结果就是8+1=9,即不存在同一位数在一次运算中出现两次进位的情况。

基于以上,我们可以声明整形变量v1, v2,分别存储链表l1, l2遍历过程中相同数位节点的值。将v1与v2相加之后,十位数存储在一个整型变量flag中,代表产生进位的情况,根据以上分析可知flag的值只会是0或1;个位数则与前一次得到的flag相加作为新的节点存储在结果链表res中。

最后,不排除最高位产生进位的情况,此时便需要在res末尾加上值位1的节点。

最终代码

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    // flag存储进位,v1、v2存储节点中的数
    int flag = 0, v1, v2;
    ListNode p1 = l1, p2 = l2, res = new ListNode(), pRes = res;
    while (p1 != null || p2 != null) {
        // p1或p2为null代表该数位为0
        v1 = p1 == null ? 0 : p1.val;
        v2 = p2 == null ? 0 : p2.val;
        // 同位数与上一位数的进位相加,个位数作为新节点
        pRes.next = new ListNode((v1 + v2 + flag) % 10);
        // 十位数作为进位
        flag = (v1 + v2 + flag) / 10;
        pRes = pRes.next;
        if (p1 != null) p1 = p1.next;
        if (p2 != null) p2 = p2.next;
    }
    // 判断最高位的进位情况
    if (flag == 1) {
        pRes.next = new ListNode(1);
    }
    return res.next;
}

执行结果

image.png