0
点赞
收藏
分享

微信扫一扫

链表题目:两数相加

律楷粑粑 2022-02-10 阅读 26
链表

文章目录

题目

标题和出处

标题:两数相加

出处:2. 两数相加

难度

3 级

题目描述

要求

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

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

示例

示例 1:

示例 1

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

示例 2:

输入: l1   =   [0],   l2   =   [0] \texttt{l1 = [0], l2 = [0]} l1 = [0], l2 = [0]
输出: [0] \texttt{[0]} [0]

示例 3:

输入: l1   =   [9,9,9,9,9,9,9],   l2   =   [9,9,9,9] \texttt{l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]} l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出: [8,9,9,9,0,0,0,1] \texttt{[8,9,9,9,0,0,0,1]} [8,9,9,9,0,0,0,1]

数据范围

  • 每个链表中的结点数在范围 [1,   100] \texttt{[1, 100]} [1, 100]
  • 0 ≤ Node.val ≤ 9 \texttt{0} \le \texttt{Node.val} \le \texttt{9} 0Node.val9
  • 题目数据保证列表表示的数字不含前导零

解法

思路和算法

由于给定的两个链表中,每位数字按照从低到高的顺序存储,因此同时从两个链表的头结点开始依次遍历两个链表,在两个链表中遍历到的结点对应的数位是相同的,即都是个位、都是十位、都是百位等。相同数位的数字可以直接相加,相加过程中会产生进位。

同时遍历两个链表,遍历过程可分为三个阶段:两个链表都有结点、只有一个链表有结点、只有进位部分。

第一阶段,两个链表都有结点。记两个链表中遍历到的结点分别为 node 1 \textit{node}_1 node1 node 2 \textit{node}_2 node2,进位值为 carry \textit{carry} carry,则两个结点对应的和结点的值为 ( node 1 + node 2 + carry )   m o d   10 (\textit{node}_1 + \textit{node}_2 + \textit{carry}) \bmod 10 (node1+node2+carry)mod10,进位值为 ⌊ node 1 . val + node 2 . val + carry 10 ⌋ \Big\lfloor \dfrac{\textit{node}_1.\textit{val} + \textit{node}_2.\textit{val} + \textit{carry}}{10} \Big\rfloor 10node1.val+node2.val+carry,将进位值更新到 carry \textit{carry} carry

第二阶段,只有一个链表有结点。如果两个链表的长度不同,则其中的一个链表会先遍历完,然后只剩下一个链表还有结点。此时可以将已经遍历完的链表对应的结点值看成 0 0 0,继续遍历和计算和。

第三阶段,只有进位部分。当两个链表都遍历完时,如果 carry \textit{carry} carry 大于 0 0 0,则需要将进位值继续填入表示和的链表中,直到进位值变成 0 0 0

具体实现方面,可以创建一个哑节点,在计算表示和的链表时,将每个结点在哑节点后面依次添加,最后返回哑节点的后一个结点作为表示和的链表。

下图为计算 42 + 965 42 + 965 42+965 的例子。对于每一位,表示和的链表中的结点值等于该位的两个结点值与 carry \textit{carry} carry 之和模 10 10 10 的余数,然后更新 carry \textit{carry} carry,计算更高位。

图 1

代码

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(0);
        ListNode temp = dummyHead;
        ListNode node1 = l1, node2 = l2;
        int carry = 0;
        while (node1 != null && node2 != null) {
            int val = node1.val + node2.val + carry;
            temp.next = new ListNode(val % 10);
            carry = val / 10;
            temp = temp.next;
            node1 = node1.next;
            node2 = node2.next;
        }
        while (node1 != null) {
            int val = node1.val + carry;
            temp.next = new ListNode(val % 10);
            carry = val / 10;
            temp = temp.next;
            node1 = node1.next;
        }
        while (node2 != null) {
            int val = node2.val + carry;
            temp.next = new ListNode(val % 10);
            carry = val / 10;
            temp = temp.next;
            node2 = node2.next;
        }
        while (carry != 0) {
            temp.next = new ListNode(carry % 10);
            carry /= 10;
            temp = temp.next;
        }
        return dummyHead.next;
    }
}

复杂度分析

  • 时间复杂度: O ( max ⁡ ( m , n ) ) O(\max(m, n)) O(max(m,n)),其中 m m m n n n 分别是两个链表的长度。需要遍历两个链表中的全部结点,对于每个结点的计算为 O ( 1 ) O(1) O(1) 的时间,由于是同时遍历,因此时间复杂度取决于较长的链表长度。

  • 空间复杂度: O ( 1 ) O(1) O(1)。除了返回值以外,使用的空间复杂度是常数。

举报

相关推荐

0 条评论