题目描述
- 给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。
- 请你将两个数相加,并以相同形式返回一个表示和的链表。
- 你可以假设除了数字0之外,这两个数都不会以0开头。
个人题解(1)
本人在第一次完成该题目时,使用了分情况讨论法。代码如下:
class Solution
{
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
int jinwei(0); //记录每一次逐位相加的进位(只可能是0或1)
ListNode* traverse(new ListNode()); //记录当前遍历到的加法结果位结点
ListNode* result(traverse); //记录最终的链表按位加法运算结果
//通过一个无限循环进行加法计算
while(true)
{
//情况1:两个链表当前位置均不为空,则进行按位加法
if(l1!=nullptr && l2!=nullptr)
{
//进行按位加法,考虑到上一位的进位(出于程序逻辑简单,不单独考虑第一位)
traverse->val = l1->val + l2->val + jinwei;
//如果计算结果大于等于10,则进行进位记录处理,否则不进位
if(traverse->val >= 10)
{
traverse->val -= 10;
jinwei = 1;
}
else jinwei = 0;
//修改l1和l2指针指向下一个结点
l1 = l1->next;
l2 = l2->next;
//如果l1和l2都遍历完成,且没有进位,则直接返回结果(考虑到程序效率,编写代码时采用反逻辑)
if(l1!=nullptr || l2!=nullptr || jinwei==1)
{
traverse->next = new ListNode();
traverse = traverse->next;
}
else return result;
}
//情况2:L1链表的位置不为空且L2链表的位置为空
else if(l1!=nullptr and l2==nullptr)
{
//进行按位加法,只加L1的部分
traverse->val = l1->val + jinwei;
//如果计算结果大于等于10,则进行进位记录处理,否则不进位
if(traverse->val >= 10)
{
traverse->val -= 10;
jinwei = 1;
}
else jinwei = 0;
//修改l1指针指向下一个结点
l1 = l1->next;
//如果l1遍历完成,且没有进位,则直接返回结果,原理与上一种情况类似
if(l1!=nullptr || jinwei==1)
{
traverse->next = new ListNode();
traverse = traverse->next;
}
else return result;
}
//情况3:L2链表的位置不为空且L1链表的位置为空
else if(l2!=nullptr and l1==nullptr)
{
//进行按位加法,只加L2的部分
traverse->val = l2->val + jinwei;
//如果计算结果大于等于10,则进行进位记录处理,否则不进位
if(traverse->val >= 10)
{
traverse->val -= 10;
jinwei = 1;
}
else jinwei = 0;
//修改l2指针指向下一个结点
l2 = l2->next;
//如果l2遍历完成,且没有进位,则直接返回结果,原理与上一种情况类似
if(l2!=nullptr || jinwei==1)
{
traverse->next = new ListNode();
traverse = traverse->next;
}
else return result;
}
//情况4:两个链表的当前位置同时为空,则在判定是否需要进位后,即可退出循环
else if(l1==nullptr && l2==nullptr)
{
if(jinwei==1)
{
traverse->val = 1;
}
break;
}
}
return result;
}
};
个人题解(2)
看了力扣官方的题解以及众多大佬们的代码后,发现根本就没有必要进行复杂的分情况讨论,并且判定是否需要进位的代码可以进行进一步简化。得到的结论如下:
- 如果能够使用一种统一的算法代替需要进行分情况讨论的算法,那么一定是更好的。
- 能够使用三元运算符
?:
的地方就不要使用if
语句,因为前者的执行效率更高。
经过修改后的代码如下:
class Solution
{
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
//记录两个数字相加时可能的进位(只能是0或1)
int jinwei(0);
//分别记录两个链表的当前数字以及求和结果
int element1,element2,sum;
//分别记录结果链表中的遍历位置和结果
ListNode* traverse(nullptr);
ListNode* result;
//只要两个链表有一个链表中还有元素,则继续循环
while(l1 || l2)
{
//分别取出两个链表中的下一个数字,如果不存在下一个元素则用0表示
element1 = l1?l1->val:0;
element2 = l2?l2->val:0;
//进行相加求和
sum = element1 + element2 + jinwei;
//判断是否需要进行进位
jinwei = sum / 10;
//修改两个链表的指针位置
if(l1)l1 = l1 -> next;
if(l2)l2 = l2 -> next;
//修改结果链表的指针(需要分指针是否为空的情况)
if(!traverse)
{
traverse = new ListNode(sum % 10);
result = traverse;
}
else
{
traverse -> next = new ListNode(sum % 10);
traverse = traverse -> next;
}
}
//判断最后一位是否有进位
if(jinwei==1) traverse -> next = new ListNode(1);
//返回结果
return result;
}
};
另外,C++的语法学习上,有一个注意点:
- 指针转换为布尔值:C++中,如果将一个非空指针转换为布尔值,则结果为true;如果将一个空指针转换为布尔值,则结果为false。