LeetCode 2.Add Two Numbers

来源:互联网 发布:淘宝店铺推荐少女 知乎 编辑:程序博客网 时间:2024/06/09 19:12

一、问题描述

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in [reverse][6] order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

题意解释:给定两个链表,一个链表表示一个数,链表的每一个节点表示这个数的其中一位,链表头为最低位,链表尾为最高位。将两个数相加,所得结果仍以相同方式存进链表中。

二、解题思路

第一次尝试:
一开始认为既然两个链表的长度是未知的,可以先遍历两个链表得出其长度之后再对两个链表进行逐项相加,但是发现这个方法还能再做改进,因为它既要遍历3次链表。

第二次尝试:
想到在遍历两个链表的同时将每个节点存进queue中,对两个queue从队头开始进行相加,计算结果依次存进另外一个queue中,最后再直接由queue的每一项构造一条相加结果的链表。对链表的操作相比queue而言更为复杂,这个方法把加法过程转移到queue中操作,但坏处是增加了3个queue的开销,逻辑也不够直接

第三次尝试:
前面的两次尝试,不是时间开销过大,就是空间开销过大,都有可以改进的空间,因此可以考虑不借助其他容器且只需对两个链表各遍历一次的方法。其实这道题的难点就在于对两条不同长度链表的处理,在只遍历一次链表的情况下,链表长度是未知的,那么在进行加法运算时,就需要对节点的位置进行判断,特别是在边界部分,如一个链表到达最后一个节点而另一个链表还未到达最后一个节点,那这时候的进位如何处理,相加如何处理,需要分情况做讨论。

1、初始化一个指向结果链表头结点的指针headNode

2、tempNode一开始指向结果链表的头结点,在遍历结点进行加法运算时,tempNode指向当前构造结点的上一个结点

3、同步遍历两个链表, l1_num和 l2_num分别表示当前位数上的加数和被加数,如果链表的当前结点为空,则设该数为0,否则为该结点所存的val值

l1_num = (p != NULL) ? p->val:0;            l2_num = (q != NULL) ? q->val:0;

4、初始化进位carry=0,遍历链表的每一位时,结果链表对应位表示为

sum = (l1_num + l2_num + carry) % 10;

它给下一位造成的进位表示为

carry = (l1_num + l2_num + carry) / 10;

5、构造一个val值为sum的新结点nextNode并将tempNode的next指针指向nextNode。

ListNode* nextNode = new ListNode(sum);            tempNode->next = nextNode;

6、tempNode更新为当前的nextNode,如果指向加数链表和被加数链表当前结点的指针不为空,则同时指向下一个结点并重复以上过程,直到两个链表都已被遍历完成

三、C++代码

struct ListNode {     int val;     ListNode *next;     ListNode(int x) : val(x), next(NULL) {}};class Solution {public:    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {        int carry = 0;        int l1_num, l2_num, sum;        ListNode* headNode = new ListNode(0);        ListNode* tempNode = headNode;        ListNode* p = l1;        ListNode* q = l2;        while (p != NULL || q != NULL) {            l1_num = (p != NULL) ? p->val:0;            l2_num = (q != NULL) ? q->val:0;            sum = (l1_num + l2_num + carry) % 10;            ListNode* nextNode = new ListNode(sum);            tempNode->next = nextNode;            tempNode = tempNode->next;            if (p != NULL) p = p->next;            if (q != NULL) q = q->next;            carry = (l1_num + l2_num + carry) / 10;        }        if (carry > 0) {            tempNode->next = new ListNode(carry);        }        return headNode->next;    }};

四、复杂度分析

1、时间复杂度:
时间复杂度取决于遍历链表时重复了多少次指针移动操作,本题中这种重复操作的次数取决于较长链表的长度,即时间复杂度为 O(max(m,n))
2、空间复杂度:
空间复杂度取决于新构建的链表的长度,由于结果链表的最大可能长度为max(m,n)+1,所以空间复杂度为O(max(m,n))

原创粉丝点击