第二道题,就是理解一下链表就解决了,题目如下:

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse 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.

For example:

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

大致意思是,输入给出两个链表来代表两个非负的整数,不过这个整数是按照倒序来表示的,简单的说就是2->4->3实际上代表的是整数342,就是这样的两个整数,最后要得到这两个链表所代表整数的和,结果也按照链表的形式返回。

首先要考虑的几种情况:

1)两个链表可能不一定一样长

2)最后可能存在一个进位

3)两个链表刚好一样长

一开始的时候我本来想把这两个数拿出来,反一下,按照整数的加减法来做的,结果测试集中肯定会存在超过int范围的数存在,果然不行,所以只能一位一位的循环来加。

在使用C++来写的时候:

已经给出定义节点的结构体如下

1 /**
2  * Definition for singly-linked list.
3  * struct ListNode {
4  *     int val;
5  *     ListNode *next;
6  *     ListNode(int x) : val(x), next(NULL) {}
7  * };
8  */

也就是只需要挨个访问链表的元素,对应位上的数进行求和,计算进位,结合上面的三种情扩,最后就能得到结果,C++的代码如下

 1 class Solution {
 2 public:
 3     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
 4         int carry=0;
 5         ListNode *result=new ListNode(0);
 6         ListNode *pointer=result;
 7         while(l1!=NULL||l2!=NULL||carry){
 8             int sum=0;
 9             if(l1!=NULL){
10               sum=sum+l1->val;  
11               l1=l1->next;
12             }
13             if(l2!=NULL){
14                 sum=sum+l2->val;
15                 l2=l2->next; 
16             }
17             if(carry==1){
18                 sum=sum+1;
19             }
20             pointer->next=new ListNode(sum%10);
21             carry=sum/10;
22             pointer=pointer->next;
23         }
24         ListNode* res=result->next;
25         delete result;
26         return res;    
27     }
28 };

 由于效率不是最好的,我想了想有没有别的提高效率的方法,参考discussion,也可以这样解决,使用下面的方法,可以不用从头开始一个一个的插入元素节点,直接让l1,l2的其中一个变成最后的结果链表:

 1 class Solution {
 2 public:
 3     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
 4         int carry=0;
 5         ListNode *result=l1;
 6         while(l1!=NULL){
 7             int sum=l1->val+carry;
 8             if(l2!=NULL){
 9                 sum=sum+l2->val;
10                 l2=l2->next;
11             }
12             if(l1->next==NULL&&l2!=NULL){
13                 l1->next=l2;
14                 l2=NULL;
15             }
16             l1->val=sum%10;
17             carry=sum/10;
18             
19             if(l1->next==NULL&&carry){
20                 ListNode *tmp=new ListNode(1);
21                 l1->next=tmp;
22                 carry=0;
23             }
24             
25             l1=l1->next;
26         }
27         return result;
28     }
29 };

这个主要有一个点就是在链表l1比链表l2短的时候,需要把原来指向l1链表的指针指向l2链表使得while循环继续下去。

不过效率也没有改善多少。 

同理,使用javascript中也事先定义了节点

1 /**
2  * Definition for singly-linked list.
3  * function ListNode(val) {
4  *     this.val = val;
5  *     this.next = null;
6  * }
7  */
8 /**

在这里ListNode是作为一个函数存在的,一样的方法,使用javascript的写法如下:

 1 var addTwoNumbers = function(l1, l2) {
 2    var result=new ListNode(0);
 3    var pointer=result;
 4    var carry=0;
 5    while(l1!==null||l2!==null||carry){
 6        var sum=0;
 7        if(l1!==null){
 8            sum=sum+l1.val;
 9            l1=l1.next;
10        }
11        if(l2!==null){
12           sum=sum+l2.val; 
13           l2=l2.next;
14        }
15        if(carry){
16            sum=sum+1;
17        }
18        var tmp=new ListNode(sum%10);
19        carry=parseInt(sum/10);
20        pointer.next=tmp;
21        pointer=pointer.next;
22    }
23    return result.next;
24 };

 

总结使用到的C++知识点:

主要就是对链表进行操作,最最主要的是在链表中插入元素,

初始化一个ListNode类型的指针,ListNode *result=new ListNode(0);

pointer表示和result指向同一个地址空间的指针(都在链表头),每次新增元素赋给pointer->next,同时让pointer指向链表的下一个元素,这样直到最后返回链表头的下一个指针result->next(去掉初始化的那个),就是最终的结果。

最后其实有一个操作,就是把result->next赋给一个新的ListNode类型的指针,直接返回新赋值的指针就行了,这样要记得刚开始分配的result指针的内存空间应该使用delete进行释放(这样做实际上是会提高效率的)

在最后存在一个进位的情况,就需要new一个新的节点,并把这个新的节点加到返回链表的最后,假设当前pointer指向的链表的末尾,tmp节点是新的要加入的节点,这时候只需要tmp->next=result->next;result-next=tmp;即可,一般在链表的中间插入节点也可以用上面的方法。

 

总结使用到的javascript知识点:

由于javascript没有支持指针,节点listNode被定义为一个function,function作为object的一种,当然可以使用new来进行初始化,这样调用了function的内部属性this,表示当前执行函数的环境对象来初始化节点进行赋值操作。

 

 posted on 2017-02-04 23:24  yuruilee  阅读(146)  评论(0编辑  收藏  举报