445. Add Two Numbers II

题目

445. Add Two Numbers II

解题思路

这道题有点麻烦……题目的意思是,举个栗子:

L1:7 -> 2 -> 4 -> 3
L2: 5 -> 6 -> 4

从后往前一一对应相加,还需要考虑进位,得到新链表:

7 -> 8 -> 0 -> 7

题目要求不准把链表反转。

我第一个思路是分别计算出2个链表的和,把两个和相加得到的数不断去%10创建新链表。如果链表比较短这个方法是可以的,链表太长的话,int或long也hold不住直接溢出了。

第二个思路是先遍历计算出2个链表的长度,分成长短链表,以上面的例子讲解:

链表类型链表内容链表长度
长链表7 -> 2 -> 4 -> 34
短链表5 -> 6 -> 43

已知两者长度差为4-3=1,因此从长链表的第2个元素开始,与短链表的相加。由于要从后往前相加,因此采用递归,同时注意进位。

递归结束后,如果递归到第一个元素相加后有进位:

  • 如果长链表长度>短链表长度,则长链表与短链表相加的首元素的前一个元素,需要加1,再判断是否需要进位,如果是再加1,最后如果到第一个元素仍有进位,则在首元素前新建一个结点,并赋值为1

  • 如果长链表长度==短链表长度,则长链表前需要新建一个结点,并赋值为1

注意链表长度相同的特殊情况。

具体代码

 /**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    // 两个链表相加,递归,从后往前相加
    int add(ListNode *l1, ListNode *l2) {
        if (!l1->next && !l2->next) {
            l1->val += l2->val;
        } else {
            l1->val += l2->val + add(l1->next, l2->next);
        }
        if (l1->val >= 10) {
            l1->val -= 10;
            return 1;
        }
        return 0;   // 返回进位
    }
    // 处理长链表前面没有参与“与短链表相加”的结点
    int single_link(ListNode *l1, ListNode *l2) {
        if (l1 == l2) {
            l1->val += 1;
        } else {
            l1->val += single_link(l1->next, l2);
        }
        if (l1->val >= 10) {
            l1->val -= 10;
            return 1;
        }
        return 0;   // 返回进位

    }

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        if (!l1 || !l2) {
            return l1 ? l1 : l2;
        }
        // 获取2个链表长度
        int len1 = 0, len2 = 0;
        ListNode *t_l1 = l1;
        ListNode *t_l2 = l2;
        while (t_l1) {
            ++len1;
            t_l1 = t_l1->next;
        }
        while (t_l2) {
            ++len2;
            t_l2 = t_l2->next;
        }

        // 分出长短链表
        int longlen = len1 > len2 ? len1 : len2;
        int shortlen = len1 <= len2 ? len1 : len2;
        ListNode *longlink = len1 > len2 ? l1 : l2;
        ListNode *shortlink = len1 <= len2 ? l1 : l2;

        // 找到长链表的某个结点开始与短链表长度相同
        ListNode *t_l = longlink;
        int diff = longlen - shortlen;
        ListNode *pre_t_l = NULL; // “某个结点”的前一个结点
        while (diff--) {
            pre_t_l = t_l;
            t_l = t_l->next;

        // 让长短链表相加,判断最终有无进位    
        if(add(t_l, shortlink)) {
            // 如果pre_t_l为空说明长度链表长度相等
            // 不为空则处理长链表前面没有参与“与短链表相加”的结点
            // 如果最终有进位,则长链表的首结点前还需新建一个新结点

            if (!pre_t_l || single_link(longlink, pre_t_l)) {
                ListNode *t = new ListNode(1);
                t->next = longlink;
                longlink = t;
            }
        }

        return longlink;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值