Leetcode DAY3 两数相加

一、问题描述

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

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

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

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

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

二、问题分析

在本题中,一个整数以链表的形式存储,且按个位逆序存储,因此两个整数相加可以直接将两个链表的对应节点的值相加。若链表长度不同,则可以将短链表用0补全,对齐长链表。
在相应节点值相加时,需要注意该位的进位情况。也就是说,两数之和的每一位由两个数对应位值n1,n2加上该位的进位c,即(n1 + n2 + c)%10,该位对下一位的进位为(n1 + n2 + c)/10。并在最后一位相加时应着重注意进位,若有进位应为进位新增一个节点。
具体代码如下:

/**
 * 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:
//知识点1:单向链表
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//建立一个新的链表,其中包含一个头节点和一个尾节点
        ListNode *head = nullptr, * tail = nullptr;
        int c = 0,n1,n2,sum;
//将两个链表对应位相加,只要有一个链表该位有数即可加(链表名称即为头指针)
        while(l1||l2){
//知识点2:条件运算符
//链表该位有值则赋值,无值则赋0
        n1 = l1?l1->val:0;
        n2 = l2?l2->val:0;
//对应位相加,记得加进位
        sum = n1 + n2 + c;
//知识点3:动态内存
//判断此时是否为头节点,若是,则新节点同时替换为头节点和尾节点
        if(!head)head = tail = new ListNode(sum%10);
        else{
//若此时不是头节点,则将新节点添至末尾
        tail->next = new ListNode(sum%10);
        tail = tail->next;
        }
        c = sum / 10;
//移至下一个相加位;注:直接移动头指针很危险
        if(l1)l1 = l1->next;
        if(l2)l2 = l2->next;
        }
//判断最高位是否有进位,若有则新增一个节点
        if(c)tail->next = new ListNode(c);
//返回两数之和的新链表
        return head;
};

时间复杂度为O(max(m,n)),m和n分别为两链表的长度。空间复杂度为O(1)。

三、知识点拓展

知识点1 单向链表

在介绍单向链表之前,简单介绍一下顺序表。顺序表同链表一样,都是线性表,他们线性存储元素。顺序表顺序固定,元素相邻,因此访问元素非常快速,但增删元素则十分麻烦,在顺序表中增删一个元素,将会影响到后面的所有元素。

因此,引出链表的概念。链表也按顺序存储元素,元素在逻辑上相邻,但在物理上不相邻,要使得在实际应用中找到与前一个元素逻辑上相邻而物理不相邻的元素,采用指针来解决这个问题。链表由节点组成,一个节点包括数据域和指针域,数据域保存值,指针域保存相邻节点的地址,对于单向链表,指针域仅包含指向下一个元素的指针。
单向链表的结构
单向链表的结构如上图所示。

名词解释:

头指针:指向第一个节点的指针变量。具有标识单向链表的作用,因此常用头指针代替链表名称。

头节点:存储具体元素的首元节点前的节点。可以不存储元素,也可以存储链表长度等信息。用于统一空链表和非空链表操作的节点。
*若不存在头节点,在非空链表中进行节点的增删,需要对前一个节点指向的下一个节点地址进行修改,并将指向尾节点的指针进行修改;而在空链表中,只需要将头指针指向的节点进行更改。两者操作不一致,因此需要头节点来进行操作统一。(however,实际应用中并不一定需要头节点,比如本题的解就没有使用kkk)

首元节点:存储第一个元素的节点。

知识点2 条件运算符

n1 = l1?l1->val:0;

条件?选项1:选项2;
若满足条件,则赋值选项1的值,否则赋值选项2的值。

参考文献:条件运算符

知识点3 动态内存

C++程序的内存分为栈、堆。栈内存是在声明变量时分配好的内存,堆内存是程序运行时动态分配的内存。

在不确定需要多少内存时,可使用特定运算符给指定类型变量分配堆内存,返回的是存储空间的地址。特定运算符如new,delete。

//分配double类型的动态内存
double *p = nullptr;
p = new double;
//释放内存
delete p;

参考文献:动态内存

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,Leetcode 2 "两数相加"是一个涉及链表的问题。该问题给定了两个非负整数,每个整数的每一位都是按照逆序的方式存储在链表中。我们需要将这两个链表相加,并返回一个新的链表作为结果。 具体解题思路可以使用迭代法或递归法来解决。迭代法的伪代码如下所示: ``` 初始化一个哑节点 dummy 和一个进位 carry,同时把两个链表的头节点分别赋值给 p 和 q 遍历链表,直到 p 和 q 都为 None 计算当前的和 sum 为 p.val + q.val + carry 计算当前的进位 carry 为 sum // 10 创建一个新节点 node,节点的值为 sum % 10 把新节点连接到结果链表的尾部 更新 p 和 q 分别为 p.next 和 q.next 如果最后还有进位 carry,则创建一个新节点 node,节点的值为 carry,并连接到结果链表的尾部 返回结果链表的头节点 dummy.next ``` 递归法的伪代码如下所示: ``` 定义一个辅助函数 addTwoNumbersHelper,输入为两个链表的头节点 p 和 q,以及进位 carry 如果 p 和 q 都为 None 且 进位 carry 为 0,则返回 None 计算当前的和 sum 为 p.val + q.val + carry 计算当前的进位 carry 为 sum // 10 创建一个新节点 node,节点的值为 sum % 10 设置新节点的下一个节点为递归调用 addTwoNumbersHelper(p.next, q.next, carry) 返回新节点 返回 addTwoNumbersHelper(p, q, 0) 的结果 以上是解决 Leetcode 2 "两数相加"问题的两种方法。如果你还有其他相关问题,请
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值