题目:两数相加
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个结点只存储单个数字。将两数相加返回一个新的链表。
输入:(2->4->3)+ (5->6->4)
输出: 7->0->8
原因: 342 + 465 = 807
这两个数字都不会以零开头。
try1:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode* res;
struct ListNode* cur;
struct ListNode* p;
int flag = 0;
int n1,n2;
cur = (struct ListNode*)malloc(sizeof(struct ListNode));
res = cur;
p = cur;
while(l1 != NULL || l2 != NULL){
n1 = l1 ? l1->val : 0;
n2 = l2 ? l2->val : 0;
cur = (struct ListNode*)malloc(sizeof(struct ListNode));
cur->val = n1 + n2 + flag;
if(cur->val < 0){
flag = 0;
} else {
cur->val = cur->val - 10;
flag = 1;
}
p->next = cur;
p = cur;
}
return res->next;
}
在一番努力后给出try1,但是超出内存限制,但找不到原因,有大佬指点的话,感激不尽。
在此,无奈去看看别人的代码,目前仅初步了解C语言以及JavaScript,不过语言是相通的,应该能够大概猜出来别人的意思吧。
C++ 版本
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
ListNode *res = new ListNode(-1);
ListNode *cur = res;
int carry = 0;
while (l1 || l2) {
int n1 = l1 ? l1->val : 0;
int n2 = l2 ? l2->val : 0;
int sum = n1 + n2 + carry;
carry = sum / 10;
cur->next = new ListNode(sum % 10);
cur = cur->next;
if (l1) l1 = l1->next;
if (l2) l2 = l2->next;
}
if (carry) cur->next = new ListNode(1);
return res->next;
}
};
我们来一起看看,先不管开头的class,public什么的,先是函数声明,要返回一个指向ListNode类型的指针,函数有两个参数;
res是result的缩写,这就是最后要返回的那个指针,return res->next ,这是为什么呢? 应该是头指针的缘故。接着看,“=” 右边 new,新建,C++ 把要创建的东西放在左边,而把要创建什么的写在右边?似乎也是JS的风格。
ListNode(-1),这是什么意思?往后看看,我们发现还有 ListNode(sum % 10) ListNode(1) 难道是强制类型转换的意思?把-1强制转换成ListNode类型?不要乱想,我们看看结构体中是怎么说的,明白了,ListNode(int x) 就是值为x,next为空指针的意思,这样的表达简洁、清晰、易懂;
接着又创建一个指针cur,cur是current的缩写(previous是前一个,next是后一个),为什么要创建这个指针呢?因为你要创建、读取、删除后面的结点什么的时候,要有一个移动的指针,你不能动res,res要是变了,你的链表就在茫茫内存中找不到了。往后看一眼,怎么没有动态分配的语句?就是像 (ListNode*)malloc(sizeof(LIstNode))这样的部分?
carry是考虑进位问题所设;
接下来一个while循环,循环判断语句 (l1 || l2) 实际上是 ((l1 != NULL) ||(l2 != NULL)) 的缩写,这样code更简洁,下同;
条件运算符(?: ) 求和 取整 取余
cur->next = new ListNode(sum % 10);
这行起到了什么作用?1.创建的新结点;2.赋值 sum%10 给 cur->next 的val部分
cur = cur->next;
继续向后;
if (l1) l1 = l1->next;
if (l2) l2 = l2->next;
如不为空,l1 l2 也向后;
if (carry) cur->next = new ListNode(1);
循环结束后,如果carry非空,就再创建一个结点,并赋值1,那我们就可以肯定了ListNode(1),括号中是要赋的值。cur->next 指针所指处,new一块ListNode类型大小的地址,并赋值。
换种表达,剑锋所指,开辟领土,为之加冕。
提交通过了,但我们的学习还没有结束。
延伸:
new 和 malloc 的区别与联系;
如果链表中的数字不是按逆序存储呢?
e.g.(3->4->2)+(4->6->5)=(8->0->7)