LeetCode 刷题 2. 两数相加

题目

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

备用知识-C++ ListNode

ListNode是链表的一个节点结构体,通常在C++中用结构体来实现。

struct ListNode { 
int val; // 节点的值 
ListNode *next; // 指向下一个节点的指针
 ListNode(int x) : val(x), next(NULL) {} // 构造函数 
};

其中val表示节点的值,next是指向节点的下一个节点的指针,为NULL表示该节点是最后一个节点。构造函数用于初始化节点的值和下一个节点的指针。
通过定义ListNode结构体,可以方便地创建一个链表。
例如:

ListNode* head = new ListNode(1); // 创建头结点 
ListNode* p1 = new ListNode(2); // 创建第一个节点 
ListNode* p2 = new ListNode(3); // 创建第二个节点
head->next = p1; // 头结点指向第一个节点 
p1->next = p2; // 第一个节点指向第二个节点
#include <iostream>
using namespace std;

//定义结构体
struct ListNode {
	int val;  //节点的值
	ListNode* next;  //指向下一个节点的指针
	//构造函数用于初始化节点的值和下一个节点的指针
	ListNode(int x) : val(x), next(NULL) {}; //构造函数,为空,表示该节点是最后一个节点。
	ListNode(int x, ListNode* y) { val = x; next = y; }
};


int main()
{
	//方法1
	ListNode* head = new ListNode(1); //创建头节点
	ListNode* p1 = new ListNode(2); //创建第一个节点
	ListNode* p2 = new ListNode(3); //创建第二个节点
	head->next = p1; // 头节点指向第一个节点
	p1->next = p2; // 头节点指向第二个节点

	//方法2
	ListNode* pp = new ListNode(1, new ListNode(2, new ListNode(3)));
}

解题思路

思路及算法:
1.两个链表都是逆序的,因此相同的位置可以直接相加;
2. 同时遍历两个链表,逐位进行相加,并与当前的进位进行相加;具体而言,如果当前位置相应的两个数分别位n1,n2,进位制为carry,那么当前的和的数值为n1 + n2 + carry;其中,答案链表处的数值为(n1 + n2 + carry)mod 10, 进位值为[(n1 + n2 + carry) / 10], 即取整;
3. 如果两个链表的长度不同,则短的后面位置可默认为0;
4. 如果链表遍历结束后,有carry >0 ,则还需在后面添加一个节点,节点值为carry。

#include
using namespace std;

//定义结构体
struct ListNode {
    int val;  //节点的值
    ListNode* next;  //指向下一个节点的指针
    //构造函数用于初始化节点的值和下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}; //构造函数,为空,表示该节点是最后一个节点。
    ListNode(int x, ListNode* y) { val = x; next = y; }
};

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* head = nullptr, * tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val : 0;  //逐位读取,l1与l2谁短谁补零
            int n2 = l2 ? l2->val : 0;  //逐位读取
            int sum = n1 + n2 + carry;  //求和
            if (!head) {
                head = tail = new ListNode(sum % 10);  //如果head为空,则首尾指向同一个值
            }
            else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;  //计算当前进位值
            if (l1) {
                l1 = l1->next;  //将剩余的next指向的数据赋给l1,相当于删除已经计算的节点
            }
            if (l2) {
                l2 = l2->next;  //将剩余的next指向的数据赋给l1
            }
        }
        if (carry > 0) {
            tail->next = new ListNode(carry);  //如果carry>0,则需要额外添加一个节点
        }
        return head;
    }
};


int main()
{

	ListNode* head = new ListNode(1); //创建头节点
	ListNode* p1 = new ListNode(2); //创建第一个节点
	ListNode* p2 = new ListNode(3); //创建第二个节点
	head->next = p1; // 头节点指向第一个节点
	p1->next = p2; // 头节点指向第二个节点


    ListNode* qhead = new ListNode(1); //创建头节点
    ListNode* q1 = new ListNode(2); //创建第一个节点
    ListNode* q2 = new ListNode(3); //创建第二个节点
    qhead->next = q1; // 头节点指向第一个节点
    q1->next = q2; // 头节点指向第二个节点


    Solution solution;

    solution.addTwoNumbers(head, qhead);

}

复杂度分析

时间复杂度:O(max(m, n)),最长的节点的个数
空间复杂度:O(1),没有添加额外的空间,返回值不计入空间复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值