Leetcode链表题目笔记3 链表求和

这篇博客介绍了如何使用链表来表示两个反向存放和正向存放的数字,并对其进行求和。对于反向存放的链表,可以逐位相加并处理进位,采用尾插法构建结果链表。而对于正向存放的链表,需要先将链表元素入栈,然后出栈进行求和,使用头插法构建结果链表。两种方法都确保了正确计算和链表的正确构造。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面试题 02.05. 链表求和:以链表的形式完成两个数字的求和,并以链表的形式输出

给定两个用链表表示的整数,每个节点包含一个数位。

这些数位是反向存放的,也就是个位排在链表首部。

编写函数对这两个整数求和,并用链表形式返回结果。

示例:

输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
输出:2 -> 1 -> 9,即912

进阶:思考一下,假设这些数位是正向存放的,又该如何解决呢?

示例:

输入:(6 -> 1 -> 7) + (2 -> 9 -> 5),即617 + 295
输出:9 -> 1 -> 2,即912

结合两个链表的遍历以及两数按位求和并考虑进位两个操作。

反向存放的情况更为简单,因为从低位到高位进行计算,有进位便向上传递,若其中一个链表先结束,另外一个链表继续进行计算,最后等两个链表都结束且进位为0便停止;每次计算对应位以及进位之和后,添加一个新的链表结点用于存放结果链表的数字,最后反馈结果链表的头节点。

需要注意的是,反向存放情况下输出的链表同样采用反向存放的方式,从低位到高位,所以构建结果链表时采用尾插法即可。

(1)定义虚拟头结点,用于指向最终输出的结果链表;

(2)定义当前两个链表对应位数字之和sum以及进位carry;

(3)两个链表各对应位相加得到sum,sum再加上进位carry,以sum%10为val建立结果链表中的新的结点,更新进位carry,指针后移;

(4)两个链表均结束,且进位carry=0时,结束循环,反馈结果链表头节点。

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummyHead = new ListNode(0);
        ListNode* cur = dummyHead;
        int sum = 0, carry = 0;
        while(l1 != NULL || l2 != NULL || carry != 0){
            sum = 0;
            if(l1 != NULL){
                sum += l1->val;
                l1 = l1->next;
            }
            if(l2 != NULL){
                sum += l2->val;
                l2 = l2->next;
            }
            sum += carry;
            carry = sum / 10;
            ListNode* temp = new ListNode(sum % 10);
            cur->next = temp;
            cur = cur->next;
        }
        return dummyHead->next;
    }
};

正向存放的情况更加复杂,如果采用类似的直接遍历的方法,由于链表从高位开始,那么不能实现从低位到高位的进位,并且在两个链表长度不一定一致的情况下,直接遍历是无法对应各位的。因此,结合栈的性质,首先将两个链表各结点依次存放到两个栈中,再对两个栈中的元素依次出栈进行与反向存放情况下类似的操作即可。

同样需要注意的是,正向存放情况下输出的链表采用正向存放的方式,从高位到低位,那么构建结果链表时应采用头插法,这与反向存放的情况也不同。

class Solution {
public:  
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> st1, st2;
        while (l1 || l2) {
            if (l1) {
                st1.push(l1->val);
                l1 = l1->next;
            }
            if (l2) {
                st2.push(l2->val);
                l2 = l2->next;
            }
        }
        ListNode* dummyHead = new ListNode(-1);
        int carry = 0, sum = 0;
        while (!st1.empty() || !st2.empty() || carry != 0) {
            sum = 0;
            if (!st1.empty()) {
                sum += st1.top();
                st1.pop();
            }
            if (!st2.empty()) {
                sum += st2.top();
                st2.pop();
            }
            sum += carry;
            carry = sum / 10;
            ListNode* temp = new ListNode(sum % 10);
            temp->next = dummyHead->next;
            dummyHead->next = temp;
        }
        return dummyHead->next;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值