leetcode速度才是王道 2. Add Two Numbers

2. Add Two Numbers

You are given two linked lists representing two non-negative numbers. 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.

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

  题目的意思是将两个非负数放到两个链表list1和list2,链表的存储方式是高位在右低位在左(类似小端模式存储,这样的效果是往右边进位),而且每个节点都只能饿保存一位数。然后需要设计一个算法将两个非负数相加,将结果以之前规则的链表形式返回。题目很直接,没有啥让人疑惑的地方,下面开始第一次尝试:

  为了减少内存的分配次数,最开始的想法是先求出两个链表的长度,使用长的来保存计算出来的结果,如果最后有进位的话只需要重新分配一个节点的内存。代码如下:

 1 struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
 2     struct ListNode *head, *p, *res = l1;
 3     struct ListNode *q, *tmp = l2;
 4
 5     int l1Length = 0;
 6     int l2Length = 0;
 7     p = l1;
 8     q = l2;
 9     while(1)
10     {
11         if(l1)
12         {
13             l1 = l1->next;
14             l1Length++;
15         }
16         if(l2)
17         {
18             l2 = l2->next;
19             l2Length++;
20         }
21         if(!(l1 || l2))
22             break;
23         if( !(l1Length == l2Length))
24             break;
25     }
26     if(l2Length > l1Length)
27     {
28         res = q;
29         tmp = p;
30     }
31
32     head = res;
33
34     int carry = 0;
35     p = res;
36     while(1)
37     {
38         if(tmp)
39         {
40             res->val += tmp->val + carry;
41             carry = res->val / 10;
42             res->val = res->val % 10;
43
44             p = res;
45             res = res->next;
46             tmp = tmp->next;
47         }
48         else
49         {
50             if(res)
51             {
52                 res->val += carry;
53                 carry = res->val / 10;
54                 res->val = res->val % 10;
55                 p = res;
56                 res = res->next;
57             }
58             else if(carry)
59             {
60                 struct ListNode *cur = (struct ListNode*)malloc(sizeof(struct ListNode));
61                 cur->val = carry;
62                 cur->next = NULL;
63                 p->next = cur;
64                 return head;
65             }
66             else
67                 return head;
68         }
69     }
70     return NULL;
71 }

代码中用res指针来指向长的那个链表,作为保存结果的链表,用carry来记录是否进位,运行的结果是:

Runtime: 20 ms  这个与最快的16ms还有差距的,于是开始了第二次尝试

  第二次尝试的方向删除比较两个链表长度的部分,因为两个链表节点都是相同类型,所以我们可以任意拼接。 代码如下:

 1 struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
 2     struct ListNode head, *p;
 3     p = &head;
 4
 5     int carry = 0;
 6
 7     while(1)
 8     {
 9         if(l1 && l2)
10         {
11             l1->val += (l2->val + carry);
12             carry = l1->val / 10;
13             l1->val = l1->val % 10;
14
15             p->next = l1;
16             p = l1;
17
18             l1 = l1->next;
19             l2 = l2->next;
20         }
21         else if(l1)
22         {
23             l1->val += carry;
24             carry = l1->val / 10;
25             l1->val = l1->val % 10;
26
27             p->next = l1;
28             p = l1;
29
30             l1 = l1->next;
31         }
32         else if(l2)
33         {
34             l2->val += carry;
35             carry = l2->val / 10;
36             l2->val = l2->val % 10;
37
38             p->next = l2;
39             p = l2;
40
41             l2 = l2->next;
42         }
43         else if(carry)
44         {
45             struct ListNode *cur = (struct ListNode*)malloc(sizeof(struct ListNode));
46             cur->val = 1;
47             cur->next = NULL;
48             p->next = cur;
49             return head.next;
50         }
51         else
52             return head.next;
53     }
54     return NULL;
55 }

  需要注意的是因为我们并不知道哪一个该作为保存结果的list,为了保证wihle循环里的一致性,这个地方的我们先定义一个ListNode的实例head,然后定义一个指向head的指针p,这样while循环里每次得到一个节点都放到p节点后面,然后将该节点的地址赋值给p就行了,使用p来记录result链表的走向,最后返回的head.next就能返回正确结果,运行的结果是:

Runtime: 20 ms 速度竟然没有任何改变!!! 看来比较两个链表长度的操作并没有怎麽耗时,好吧,只能再从别的角度突破了

  第三次的尝试方向是再次是否还能继续较少内存,因为list2链表里的内存是等着释放的,所以完全可以使用来存储进位,也就是最后将list1和list2合并成了一个链表,用list2的头结点来保存进位,这样完全可以不用分配内存。代码如下

 1 struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
 2     struct ListNode head, *p, *end;
 3     p = &head;
 4     end = NULL;
 5
 6     int carry = 0;
 7
 8     while(1)
 9     {
10         if(l1 && l2)
11         {
12             l1->val += (l2->val + carry);
13             carry = l1->val / 10;
14             l1->val = l1->val % 10;
15
16             p->next = l1;
17             p = p->next;
18             l1 = l1->next;
19             !end && (end = l2);
20             l2 = l2->next;
21         }
22         else if(l1)
23         {
24             l1->val += carry;
25             carry = l1->val / 10;
26             l1->val = l1->val % 10;
27
28             p->next = l1;
29             p = p->next;
30             l1 = l1->next;
31         }
32         else if(l2)
33         {
34             l2->val += carry;
35             carry = l2->val / 10;
36             l2->val = l2->val % 10;
37
38             p->next = l2;
39             p = l2;
40
41             l2 = l2->next;
42         }
43         else if(carry)
44         {
45             if( !end )
46             {
47                 end = (struct ListNode*)malloc(sizeof(struct ListNode));
48             }
49             end->val = 1;
50             end->next = NULL;
51             p->next = end;
52             return head.next;
53         }
54         else
55             return head.next;
56     }
57     return NULL;
58 }

  代码中定义了一个指向end的指针,在代码19行将链表2的头结点地址赋值给了end,48~51行表示如果有进位,那麽使用end所指向的list2头结点来保存进位,并加在result结点后面,这样不用分配内存了,运行结果是:

 Runtime: 16 ms     终于达到了最快的速度 !!!有图有真相,You are here !

时间: 2024-10-03 23:10:38

leetcode速度才是王道 2. Add Two Numbers的相关文章

leetcode速度才是王道 1.Two Sum

1. Two Sum Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please

LeetCode 445. 两数相加 II(Add Two Numbers II)

445. 两数相加 II 445. Add Two Numbers II 题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. 进阶: 如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转. LeetCode445. Add Two Numbers II中等 示例: 输入: (7 -> 2 -> 4 -> 3) + (5 ->

LeetCode 2:两数相加 Add Two Numbers

?给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字.如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和. 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 cont

重内容,轻语言,优先的产品才是王道,HTML5不能代表一切

两月余前,关于FACEBOOK放弃HTML5而改用原生的事被炒的沸沸扬扬,一时间HTML5的处境下滑冰点,归其原因是"慢".Webkit的解析过程先后需要经过解析.建立DOM树.获取对应资源.布局.建立渲染树.绘图到展示.这跟传统的商品流通路径非常相似:工厂.品牌公司.总代理.经销商.卖场.消费者.由于环节太多层层加价,产品到达消费者手里往往价格居高不下.而HTML5的代价同样是用户为使用产品而付出的时间成本.原生就好比F2C,用户直接从"工厂"即本机获取产品/服务

技术才是王道、程序员修炼必备武器

信息技术的发展时间虽然不长,但其爆炸式的发展速度使信息技术迅速覆盖社会和人类生活的各个角落.程序员们是这场信息化浪潮的见证者之一,更是其中的主要参与者,这是时代赋予每个程序员的机会和责任. 信息技术的更新速度是惊人的,程序员的职业生涯则是一个要求不断学习的过程,永远不能固步自封.本人在工作期间曾看见过很多程序员只要有闲暇时间就?浏览一些没有太大作用的网页,在网上聊天,打游戏,浪费了大量的时间,十分不可取.而另外一种情况是,IT技术的日新月异使很多程序员眼花缭乱,什么都想?学,却又不知从何学起,今

leetcode -day20 Add Two Numbers

1.  Add Two Numbers You are given two linked lists representing two non-negative numbers. 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. Input: (2 -> 4 ->

LeetCode --- 2. Add Two Numbers

题目链接:Add Two Numbers You are given two linked lists representing two non-negative numbers. 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. Input: (2 -> 4 -> 3

【LeetCode】Add Two Numbers

You are given two linked lists representing two non-negative numbers. 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. Input: (2 -> 4 -> 3) + (5 -> 6 ->

LeetCode: Add Two Numbers 题解

You are given two linked lists representing two non-negative numbers. 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. Input: (2 -> 4 -> 3) + (5 -> 6 ->