445. 两数相加 II [力扣]

1.题目

在这里插入图片描述
在这里插入图片描述

2.分析

思路1:利用双指针,计算出两者长度相差多少
思路2:先逆序链表,从前向后构造新链表

3.代码

思路1:暴力

利用双指针,求解两个链表长度相差多少,而后依次存储每一位,构造新链表
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* p1 = l1, *p2 = l2;
        while(p1 && p2){
            p1 = p1 -> next; 
            p2 = p2 -> next;
        }
        int k1 = 0, k2 = 0;
        while(p1){
            ++k1;
            p1 = p1 -> next;
        }
        while(p2){
            ++k2;
            p2 = p2 -> next;
        }
        int res[110];
        int k = 0;
        ListNode* dummy = new ListNode(-1);
        ListNode* newhead = dummy;          
        if(k1 >= k2){ //l1 的 长度较长
            p1 = l1, p2 = l2;
            while(k1--){
                res[k++] = p1 -> val;
                p1 = p1 -> next;
            }
            while(p1 && p2){
                res[k++] = p1 -> val + p2 -> val;
                p1 = p1 -> next;
                p2 = p2 -> next;
            }
            for(int i = k - 1; i > 0; --i){
                res[i-1] += res[i] / 10;
                res[i] %= 10;
            }
            int inithead = res[0] / 10;
            res[0] %= 10;

            if(inithead){
                ListNode* n = new ListNode(inithead);
                dummy -> next = n;
                dummy = dummy -> next;
            }
            for(int i = 0; i < k; ++i){
                //printf("%d ",res[i]);
                ListNode* node = new ListNode(res[i]);
                dummy -> next = node;
                dummy = dummy -> next;
            }
        }else{ //l2 长度较长
            p1 = l1, p2 = l2;
            while(k2--){
                res[k++] = p2 -> val;
                p2 = p2 -> next;
            }
            while(p1 && p2){
                res[k++] = p1 -> val + p2 -> val;
                p1 = p1 -> next, p2 = p2 -> next;
            }
            for(int i = k -1; i > 0; --i){
                res[i-1] += res[i] / 10;
                res[i] %= 10;
            }
            int inithead = res[0] / 10;
            res[0] %= 10;
            if(inithead){
                ListNode* node = new ListNode(inithead);
                dummy -> next = node;
                dummy = dummy -> next;
            }
            for(int i = 0; i < k; ++i){
                ListNode* node = new ListNode(res[i]);
                dummy -> next = node;
                dummy = dummy -> next;
            }
        }
        return newhead -> next;
    }
};

思路2:逆序相加

反转链表,相加,再反转新链表即可
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        //逆序l1 l2
        l1 = reverseList(l1);
        l2 = reverseList(l2);
        //构建l3
        ListNode* dummy = new ListNode(-1);
        ListNode* l3 = dummy;
        ListNode* p1 = l1, *p2 = l2;
        int t = 0;   //注意初始化为0 ,否则为随机值
        int k = 0;
        while(p1 && p2){
            t += p1 -> val + p2 -> val;
            ListNode* node = new ListNode(t % 10);
            dummy -> next = node;
            dummy = dummy -> next;
            t /= 10;
            p1 = p1 -> next, p2 = p2 -> next;
        }
        while(p1){
            t += p1 -> val;
            ListNode* node = new ListNode(t % 10);
            dummy -> next = node;
            dummy = dummy -> next;
            t /= 10;
            p1 = p1 -> next;
        }
        while(p2){
            t += p2 -> val;
            ListNode* node = new ListNode(t % 10);
            dummy -> next = node;
            dummy = dummy -> next;
            t /= 10;
            p2 = p2 -> next;
        }
        if(t){
            ListNode* node  = new ListNode(t);
            dummy -> next = node;
            dummy = dummy -> next;
        }
        dummy -> next = nullptr;
        l3 = reverseList(l3->next);
        return l3;
    }

    ListNode* reverseList(ListNode* head){
        if(head == nullptr || head -> next == nullptr) return head;
        ListNode* newhead = reverseList(head -> next);
        head -> next -> next = head;    //head -> next 指向的是,head之后逆序链表的尾部
        head -> next = nullptr;    
        return newhead;
    }

    // void Print(ListNode* head){
    //     auto t = head;
    //     while(t){
    //         printf("%d ",t -> val);
    //         t = t -> next;
    //     }
    // }
};

思路3:栈 [要加强逆序问题考虑栈的想法]

利用栈的先入后出特性,同时,插入节点时头插,则相当于逆序新链表,得到真正的结果
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack <int> s1,s2;
        while(l1){
            s1.push(l1 -> val);
            l1 = l1 -> next;
        }
        while(l2){
            s2.push(l2 -> val);
            l2 = l2 -> next;
        }

        int t = 0; //进位
        ListNode* l3 = new ListNode(-1);
        while(!s1.empty() || !s2.empty() || t){ //栈不空 或者 t非零
            //栈不空, 则弹出栈顶
            int a = s1.empty() ? 0 : s1.top();
            int b = s2.empty() ? 0 : s2.top();
            if(!s1.empty()) s1.pop();
            if(!s2.empty()) s2.pop();

            t += a + b;  //更新记录
            //直接头插,相当于逆序存储
            ListNode* node = new ListNode(t % 10);
            node -> next = l3 -> next;
            l3 -> next = node;
            t /= 10;   //更新进位
        }
        return l3 -> next;
    }
};

4.总结

递归、链表反转、栈

5.更新日志

2022.10.3

欢迎交流、讨论、指正~
不正确、不理解之处欢迎评论留言~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值