【LeetCode】2.两数相加(中等)

【被OJ毒打的第八天】LeetCode_中等_2.两数相加

点此去做

题干:
    给出两个非空的链表用来表示两个非负的整数,我们将这两个数相加,返回一个新的链表来表示它们的和
提示:
    它们各自的位数是按照逆序的方式存储的
    每个节点只能存储一位数字
    除了数字 0 之外,这两个数的尾结点都不会是 0
输入:
    (2->4->3) + (5->6->4)
输出:
    7->0->8    // 342 + 465 = 807

1.我的做法

执行用时:32~40ms,10.4MB

思想:用一个额外的变量记录进位;遍历链表,将对应位置的数以及进位相加计算出一个临时值,接着判断这个临时值有没有超过 10,如果超过需要进位

实现:傻瓜式实现,有大量冗余代码

踩坑:注意用例 [5] + [5] = [0,1],即当两个链表都为空但有进位时的处理!

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    if (l1 == NULL) {
        return l2;
    }
    if (l2 == NULL) {
        return l1;
    }
    ListNode* res = new ListNode(-1);
    ListNode* p = res;
    int up = 0;  // 存储进位
    while (l1 != NULL && l2 != NULL) {
        int tmp = l1->val + l2->val + up;
        if (tmp >= 10) {
            up = 1;
            p->next = new ListNode(tmp - 10);
        } else {
            up = 0;
            p->next = new ListNode(tmp);
        }
        p = p->next;
        l1 = l1->next;
        l2 = l2->next;
    }
    while (l1 != NULL) {
        int tmp = l1->val + up;
        if (tmp >= 10) {
            up = 1;
            p->next = new ListNode(tmp - 10);
        } else {
            up = 0;
            p->next = new ListNode(tmp);
        }
        p = p->next;
        l1 = l1->next;
    }
    while (l2 != NULL) {
        int tmp = l2->val + up;
        if (tmp >= 10) {
            up = 1;
            p->next = new ListNode(tmp - 10);
        } else {
            up = 0;
            p->next = new ListNode(tmp);
        }
        p = p->next;
        l2 = l2->next;
    }
    if (up == 1) {
        p->next = new ListNode(1);
    }
    return res->next;
}

2.进阶做法

执行用时:24~36ms,10.3MB

思想:大致同上,但是实现做了精简和优化

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode* head = new ListNode(-1);
    int carry = 0;
    int x, y;
    int sum;
    ListNode* curr = head;
    while (l1 != NULL || l2 != NULL) {
        x = (l1 ? l1->val : 0);
        y = (l2 ? l2->val : 0);
        sum = x + y + carry;
        carry = sum / 10;
        curr->next = new ListNode(sum % 10);
        if (l1)
            l1 = l1->next;
        if (l2)
            l2 = l2->next;
        curr = curr->next;
    }
    if (carry == 1) {
        curr->next = new ListNode(1);
    }
    return head->next;
}

其他 12~24ms 的样例代码执行出来之后时间也在 24~36ms 左右...而且思路实现几乎没有什么不同......

3.另类解法

执行用时:32ms,10.5MB(在 Java 解法中能排到前 7%,可惜在 C++ 中似乎没有这么好的表现)

思想:递归,将前一位运算结果也传入函数,以此来判断是否进位

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        return addTwoNumbers(l1, l2, NULL);
    }
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2, ListNode* prev) {
        int val1 = 0;
        int val2 = 0;
        if (l1 != NULL) {
            val1 = l1->val;
            l1 = l1->next;
        }
        if (l2 != NULL) {
            val2 = l2->val;
            l2 = l2->next;
        }
        ListNode* n = new ListNode(val1 + val2);
        if (prev != NULL) {
            if (prev->val >= 10) {
                prev->val -= 10;
                n->val += 1;
            }
        }
        if (l1 != NULL || l2 != NULL) {
            n->next = addTwoNumbers(l1, l2, n);
        } else if (n->val >= 10) {
            n->next = addTwoNumbers(l1, l2, n);
        }
        return n;
    }
};

中等题目相比简单题目果然还是有点东西的~目前感觉主要表现在需要考虑的边缘情况更多了,必要的步骤也更多了,所以代码整体的执行时间都会有所增加~

今晚花旗杯开会了→_→所以很可能明后天要鸽一鸽...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值