第一次使用领扣,按照他的题目排列顺序,选择了一道中等难度的题目。由于算法课程还没有很深入,因此没有选择课程相关题目。
这道题的难点主要在于使用了链表表示数字,这样做导致三个地方的处理需要十分谨慎:
- 链表的链接
- 两数字数位不相等时,较长的数字需要再次加上去
- 两位数所有位数加完后,是否会产生进位
而由于最高位在链表尾端,反而使得运算变得简单,不需要对齐操作。
- 由一首一尾两个指针指向产生的新数字,每次得出新的一位,就更新尾端,最后返回首指针
- 计算每一位时,得到结果后取十位作为进位,个位作为结果位
- 先计算两个数字的共同位数,计算完成后,再计算较长的数字的剩余位,计算完成后,计算进位
- 野指针问题
在创建新的数字链表过程中,使用了一个指针不停的
new
并指向next
,并且用头节点(头节点为空时)与尾节点(头节点不为空时)指向它。
struct ListNode* l3;
int add = 0;
struct ListNode* t1 = l1;
struct ListNode* t2 = l2;
struct ListNode* tail;
struct ListNode* t3;
while (t1 -> next != NULL && t2 -> next != NULL) {
int temp = t1 -> val + t2 -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t1 = t1 -> next;
t2 = t2 -> next;
t3 = t3 -> next;
}
但是在编译的过程中,却出现了这样的错误:
reference binding to misaligned address 0x5f5f7472617473 for type 'const int', which requires 4 byte alignment
出现绑定错误的问题,当l3 = t3
赋值的时候,无法绑定地址,在查阅资料后,对所有的指针进行了初始化操作,再次编译,结果正常。
struct ListNode* l3 = NULL;
int add = 0;
struct ListNode* t1 = l1;
struct ListNode* t2 = l2;
struct ListNode* tail = NULL;
struct ListNode* t3 = NULL;
- 共同最高位无法计算
在循环中,判断的条件为
t1 -> next != NULL && t2 -> next != NULL
,但是在实际的操作中,共同的最高位时无法计算的,例如:[1,2,3] + [1,2,3]
,在计算到3
时,就已经不在判断条件范围之内了,为了解决这个问题,我在循环结束后,单独进行了一次相同的运算,确保共同最高位能够被计算。
//计算共同最高位
{
int temp = t1 -> val + t2 -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t1 = t1 -> next;
t2 = t2 -> next;
t3 = t3 -> next;
}
- 判断是否等长
我使用了新的指针指向了较长的那一个数字剩余部分的最低位,并且以此为判断条件,继续运算:
//计算剩余位
{
struct ListNode* t = NULL;
if (t1 != NULL) {
t = t1;
}
if (t2 != NULL){
t = t2;
}
while (t -> next != NULL) {
int temp = t -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t = t -> next;
t3 = t3 -> next;
}
在操作中,发现如下报错:
Line 59: member access within null pointer of type 'struct ListNode'
当两个数字等长时,则得到的新指针是空的,因此是无法指向下一个next
的,因此,在循环开始之前加上判断的部分:if (t != NULL)
进位部分较为简单,没有什么问题。
/**
* 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) {
struct ListNode* l3 = NULL;
int add = 0;
struct ListNode* t1 = l1;
struct ListNode* t2 = l2;
struct ListNode* tail = NULL;
struct ListNode* t3 = NULL;
while (t1 -> next != NULL && t2 -> next != NULL) {
int temp = t1 -> val + t2 -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t1 = t1 -> next;
t2 = t2 -> next;
t3 = t3 -> next;
}
//计算共同最高位
{
int temp = t1 -> val + t2 -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t1 = t1 -> next;
t2 = t2 -> next;
t3 = t3 -> next;
}
//计算剩余位
{
struct ListNode* t = NULL;
if (t1 != NULL) {
t = t1;
}
if (t2 != NULL){
t = t2;
}
if (t != NULL) {
while (t -> next != NULL) {
int temp = t -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t = t -> next;
t3 = t3 -> next;
}
{
int temp = t -> val + add;
t3 = new struct ListNode(temp % 10);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
add = temp / 10;
t = t -> next;
t3 = t3 -> next;
}
}
}
//计算最高位进位
{
if (add != 0) {
t3 = new struct ListNode(add);
if (l3 == NULL) {
l3 = t3;
tail = t3;
} else {
tail -> next = t3;
tail = tail -> next;
}
}
}
return l3;
}
};