LeetCode-2.两数相加 C++实现

一.问题描述
 

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

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

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

 
二.问题思路

通常,处理链表相加的问题,可以模拟竖式加法的方式,逐位相加,同时处理进位。因为链表已经是逆序存储的,所以可以直接从头节点开始相加,这样每一位对齐,方便处理 。同时,需要考虑边界情况。

具体步骤如下:

1. 创建一个哑节点(dummy node)作为结果链表的头节点前驱,便于操作。

2. 初始化当前指针指向哑节点,进位jinwei初始化为0。

3. 遍历两个链表,直到两个链表中至少一个到达链尾。

4. 每次取出两个链表当前节点的值(如果存在),加上进位jinwei,计算当前位的总和temp。

5. temp对10取余得到当前位的值,创建新节点,并连接到结果链表。

6. 计算新的进位jinwei = temp / 10。

7. 移动两个链表的指针(如果还没到末尾的话)。

8. 需要考虑的边界情况包括:

- 两个链表长度不同,例如一个链表比另一个长,这时候要继续处理较长的链表剩下的节点。

- 最后还有进位的情况,例如999 + 1 = 1000,这时候需要在结果链表中添加一个额外的节点

9.循环结束后,返回哑节点的下一个节点作为结果链表的头节点。
代码实现

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode(0); // 创建一个哑节点作为结果链表的头节点前驱,便于操作  
        ListNode* curr = dummy;            //当前指针curr指向dummy。
        int jinwei = 0;
        //处理两个链表相同长度的部分
        while (l1 != NULL && l2 != NULL)
        {
            int temp = l1->val + l2->val + jinwei;
            if (temp >= 10)
            {
                jinwei = temp / 10;
                temp = temp % 10;
            }
            else
            {
                jinwei = 0;
            }
            curr->next = new ListNode(temp);
            curr = curr->next;
            l1 = l1->next;
            l2 = l2->next;
        }
        //处理剩余结点和最后进位不为0的情况
        ListNode* remaining = (l1 != NULL) ? l1 : l2;
        while (remaining != NULL || jinwei > 0) {
            int val = remaining ? remaining->val : 0;
            int sum = val + jinwei;
            jinwei = sum / 10;
            curr->next = new ListNode(sum % 10);
            curr = curr->next;
            if (remaining) remaining = remaining->next;
            else break; // 避免无限循环
        }
        return dummy->next;
    }
};

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

空间复杂度:O(max(n, m)),存储结果链表。


以上代码写的有点杂乱,下面给出优化后的代码,思路相同

#include <iostream>

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode dummy(0); // 哑节点简化操作
    ListNode* curr = &dummy;
    int carry = 0;
    
    while (l1 || l2 || carry) {
        int sum = carry;
        if (l1) {
            sum += l1->val;
            l1 = l1->next;
        }
        if (l2) {
            sum += l2->val;
            l2 = l2->next;
        }
        carry = sum / 10;
        curr->next = new ListNode(sum % 10);
        curr = curr->next;
    }
    
    return dummy.next;
}

解释:

  1. 哑节点:简化链表头节点的处理,避免空指针问题。

  2. 循环条件l1 || l2 || carry 确保即使链表遍历完但仍有进位时继续处理。

  3. 逐位相加:每次循环计算当前位的和(包括进位),并更新进位。

  4. 创建新节点:将当前位的值存入新节点,并移动指针。

  5. 时间复杂度:O(max(n, m)),n 和 m 分别为两个链表的长度。

  6. 空间复杂度:O(max(n, m)),存储结果链表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值