题目
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例1
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
题干解析
- 数据是采用链表逆向存储的非负整数
- 链表的节点只存一位数据,且是10进制数据。数据的存储方式是类似以个十百千万的方式存储的。
- 输入异常处理,两个数都不会以0开头
- 题目未规定数据范围
边界情况分析
- 一个数据比一个短。例如 30 + 123 前面的数据是没有百位的
- 一个数据为空。例如 134+0 = 140 题干只是提及不可能两个数为空,并未数单个不为0
- 如果两个数相加刚好进一位。例如50+50 = 100
解题思路
数据转换
一般这种题目最先想到的就是此种先转换为10进制的数,然后进行求和。最后进行转换。转换的过程是链表的基础操作过程。没什么好解释的。但是此处需要注意的是数据范围(我在此处犯了两次错误)。直接采用BigDecimal的类型进行操作。由于leetcode好像不支持import。故只作为参考
示例代码
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1.val == 0 && l1.next == null && l2.val == 0 && l2.next == null){
return new ListNode(0);
}
BigDecimal sum = getValue(l1).add(getValue(l2));
return setValue(sum);
}
public BigDecimal getValue(ListNode node){
int i = 0;
BigDecimal v1 = new BigDecimal(0);
while(node.next != null){
v1 = v1.add(new BigDecimal(node.val).multiply(new BigDecimal(10).pow(i)));
node = node.next;
i++;
}
v1 = v1.add(new BigDecimal(node.val).multiply(new BigDecimal(10).pow(i)));
return v1;
}
public ListNode setValue(BigDecimal sum){
//取模运算
ListNode node = new ListNode(sum.divideAndRemainder(new BigDecimal(10))[1].intValue());
ListNode temp = node;
sum = sum.divide(new BigDecimal(10)).setScale(0,BigDecimal.ROUND_DOWN);
while (!sum.toString().equals("0")){
temp.next=new ListNode(new Long(sum.divideAndRemainder(new BigDecimal(10))[1].intValue()).intValue());
//类似int的/操作,因为BigDecimal除法会有小数
sum = sum.divide(new BigDecimal(10)).setScale(0,BigDecimal.ROUND_DOWN);
temp = temp.next;
}
return node;
}
}
普通加法计算
这个其实就是类似在纸上运算两个数之和的方式。先加个位然后再加十位的方式。
实例代码
class Solution2 {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1.val == 0 && l1.next == null && l2.val == 0 && l2.next == null){
return new ListNode(0);
}
ListNode sum = new ListNode(0);
ListNode temp =sum;
int carry = 0;
while(l1 != null || l2 != null){
int val1 = l1 == null? 0: l1.val;
int val2 = l2 == null? 0: l2.val;
int s = val1 + val2 + carry;
//如果需要进位,则记录进位的值的大小
if(s >= 10){
temp.val = s % 10 ;
carry = s / 10;
}else{
temp.val = s;
carry = 0;
}
//只有有数据未遍历完,或者遍历完有进位产生时才会新建下一位
if((l1 != null && l1.next != null) || (l2 != null && l2.next != null)){
temp.next = new ListNode(0);
temp = temp.next;
} else {
if(carry > 0){
temp.next = new ListNode(carry);
}
}
if(l1 != null){
l1 = l1.next;
}
if(l2 != null){
l2 = l2.next;
}
}
return sum;
}
}
自己看法
我看过官方给的实例代码,基本上和我的代码差不多,但是官方给的代码实际的运行时间需要比我的代码多出30ms左右。所以就贴上了我自己的代码。此题只考了基本的链表的遍历操作+两数相加问题。没必要多做展开。