add-two-numbers

本文介绍了一种链表数值相加的算法实现,通过遍历两个表示非负数的链表并处理进位,最终返回一个新的链表作为两数之和。提供了两种方法:一种在遍历时处理长度不等的链表;另一种则通过延长较短链表来统一处理。

【题目描述】
You are given two linked lists representing two non-negative numbers.
The digits are stored in reverse order and each of their nodes
contain a single digit. Add the two numbers and return it as
a linked list.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
题目的大概含义是:给两条链表,要求对两条链表进行相加,但是必须要有进位。
【题目解答】
方法一:
分别遍历两条链表,如果一条链表长而另外一条链表短,因此在将短的遍历完成之后,退出当前循环,如果两条链表中还有一条为空则在此时,将链表结点的值加上进位,从而链接在新链表的后面,从而返回即可,注意此处需要构造一个带头结点的新链表
时间复杂度:O(N)
空间复杂度:O(N)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
        if(l1==NULL&&l2==NULL)
            return NULL;
        int flag=0;//表示进位
        ListNode *tmp=new ListNode(-1);
        ListNode *newhead=tmp;
        while(l1&&l2)
        {
            int sum=flag+l1->val+l2->val;
            flag=sum/10;
            ListNode *node=new ListNode(sum%10);
            newhead->next=node;
            newhead=newhead->next;
            l1=l1->next;
            l2=l2->next;
            //当两条链表都为空之时,即走到链表的末尾,因此此时应该跳出循环
            if(l1==NULL&&l2==NULL)
                break;
            //如果之时单条链表为空,则在此链表的后面构造新结点,等待两条链表都为空
            if(l1==NULL)
                l1=new ListNode(0);

            if(l2==NULL)
                l2=new ListNode(0);
        }
        //当将两条链表的所有结点相加完成之后,有可能最后还有一个进位
        if(flag!=0)
        {
            ListNode *node=new ListNode(flag);
            newhead->next=node;
            newhead=newhead->next;
        }
        newhead->next=NULL;
        return tmp->next;
    }
};

方法二:
此种方式是,也是利用遍历每一条链表,当走到哪一条链表为空之时,在此处并不退出此循环,而是在这个空链表的后面重新构造一个结点,并将原本为空的结点指向这个新构造的结点,当然在构造这个结点的时候,不能影响与另外一条链表相加的情况,最后直到两条链表均为空时即可。
时间复杂度:O(N)
空间复杂度:O(N)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
        if(l1==NULL&&l2==NULL)
            return NULL;
        int flag=0;//表示进位
        ListNode *tmp=new ListNode(-1);
        ListNode *newhead=tmp;
        int sum=0;
        while(l1&&l2)
        {
            sum=flag+l1->val+l2->val;
            ListNode *node=new ListNode(sum%10);
            flag=sum/10;
            newhead->next=node;
            newhead=newhead->next;
            l1=l1->next;
            l2=l2->next;
        }
        //当两条链表中有一条为空,则退出上面的循环,但是假定l1不为空,刚才的flag有进位,而l1
        //后面的数字也全为9,因此在这里还是需要进位
        while(l1!=NULL)
        {
            sum=flag+l1->val;
            flag=sum/10;

            ListNode *node=new ListNode(sum%10);
            newhead->next=node;
            newhead=newhead->next;
            l1=l1->next;
        }
        while(l2!=NULL)
        {
            sum=flag+l2->val;
            flag=sum/10;

            ListNode *node=new ListNode(sum%10);
            newhead->next=node;
            newhead=newhead->next;
            l2=l2->next;
        }
        //当将两条链表的所有结点相加完成之后,有可能最后还有一个进位
        if(flag!=0)
        {
            ListNode *node=new ListNode(flag);
            newhead->next=node;
            newhead=newhead->next;
        }
        newhead->next=NULL;
        return tmp->next;
    }
};
<think>我们正在处理LeetCode的两数相加问题(AddTwoNumbers)。题目描述:给定两个非空链表,表示两个非负整数。数字以逆序存储,每个节点存储一位数字。将两个数相加,并以相同形式返回一个表示和的链表。假设除了数字0以外,这两个数都不会以0开头。示例:输入:(2->4->3)+(5->6->4)输出:7->0->8原因:342+465=807我们需要用C语言实现。思路:1.同时遍历两个链表,逐位相加,并考虑进位。2.创建一个新的链表来存储结果,或者也可以修改其中一个链表(但通常不建议修改输入链表,除非题目允许)。3.注意两个链表长度可能不同。4.最后如果还有进位,需要额外创建一个节点。步骤:初始化:-创建一个哑节点(dummynode)作为结果链表的头节点,这样可以简化操作。-用一个指针(current)指向当前节点,初始指向哑节点。-初始化进位carry为0。遍历两个链表(l1和l2)直到都到达末尾:-取两个链表当前节点的值(如果已经到达末尾,则取0)。-计算和:sum=val1+val2+carry。-计算进位:carry=sum/10。-计算当前位的值:value=sum%10。-创建一个新节点,值为value,并将其连接到current的后面,然后current移动到下一个节点。-如果链表l1不为空,则l1移动到下一个节点;同样处理l2。检查最后是否还有进位,如果有,则再创建一个节点。返回结果:哑节点的下一个节点即为结果链表的头节点。注意:题目要求返回一个新的链表。根据引用[2]的描述,我们也可以参考一些已有的思路,但这里我们按照常规方法实现。现在,我们编写C语言代码:注意:链表节点的定义通常如下(题目已给出):structListNode{intval;structListNode*next;};代码实现:</think>### LeetCode两数相加问题解决方案 #### 问题描述 给定两个非空链表,表示两个非负整数。每位数字逆序存储(如数字 123 存储为 3→2→1),每个节点存储单个数字。将两数相加后返回新的链表(同样逆序存储)。 #### 核心思路 1. **同步遍历链表**:同时遍历两个链表,逐位相加 2. **进位处理**:维护进位值 `carry` 3. **结果存储**:创建新链表存储计算结果 4. **长度处理**:处理链表长度不一致的情况 5. **最终进位**:遍历结束后检查剩余进位 #### C语言实现 ```c struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) { struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode)); // 哑节点简化操作 dummy->val = 0; dummy->next = NULL; struct 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; // 计算进位 struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode)); newNode->val = sum % 10; // 当前位值 newNode->next = NULL; curr->next = newNode; curr = curr->next; } struct ListNode* result = dummy->next; free(dummy); // 释放哑节点 return result; } ``` #### 关键优化点 1. **哑节点技巧**:使用哑节点避免头节点特殊处理 2. **三条件循环**:`while (l1 || l2 || carry)` 同时处理: - 链表未结束 - 剩余进位不为零 3. **内存管理**: - 及时释放哑节点 - 避免内存泄漏 4. **时间复杂度**:$O(\max(m,n))$,其中 $m,n$ 为链表长度 5. **空间复杂度**:$O(\max(m,n))$(结果链表长度) #### 边界处理 1. **链表长度不同**:短链表自动补零 2. **最终进位**:最高位产生进位时新建节点 3. **空链表输入**:题目已限定非空链表 4. **进位连锁**:处理连续进位(如 999+1) > 该解法通过同步遍历和进位传递,高效处理任意长度的整数加法[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值