两个数相加。
题目:
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 contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.这个题目的算法其实就是,计算任意位数的整相加。注意,他这里是把数字倒过来了,465表示为5->6->4。
解决这道题目的核心是进位问题。
其次,还要考虑:
1、两个数字长度不同。例如:12344+1 = 12345。长度不同,实际上只有个位进行加法操作。
2、首尾数字不为0。例如:99+1 = 100。连续进位。
3、位数扩展。例如:8+7 = 15。加数都是1位,和却有2位。
代码1:比较朴素的代码,按照分析逻辑一步一步实现。
public static ListNode Solution1(ListNode l1, ListNode l2)
{
int res = l1.val + l2.val; //当前节点相加的值
ListNode listNode = new ListNode(res);
ListNode headNode = listNode;
ListNode p1 = l1.next; //指向l1
ListNode p2 = l2.next; //指向l2
//节点相加
while (p1 != null || p2 != null)
{
listNode.next = new ListNode(
(p1 == null ? 0 : p1.val) + (p2 == null ? 0 : p2.val)
);
listNode = listNode.next;
p1 = p1 == null ? null : p1.next;
p2 = p2 == null ? null : p2.next;
}
listNode = headNode;
//进位处理
while (listNode !=null)
{
if (listNode.val >= 10)
{
if (listNode.next == null)
{
listNode.next = new ListNode(1);
}
else
listNode.next.val += 1;
listNode.val %= 10;
}
listNode = listNode.next;
}
return headNode;
}
代码2:提高一下代码简洁性,像这种链表,很方便用递归去遍历,下面用递归去实现。
public static ListNode Solution2(ListNode l1, ListNode l2)
{
int sumNumber = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val);
ListNode resList = new ListNode(sumNumber < 10 ? sumNumber : sumNumber % 10);
if (l1.next == null && l2.next == null && sumNumber<10)
return resList;
else
{
if (l1.next == null) l1.next = new ListNode(sumNumber >= 10 ? 1 : 0);
else if(sumNumber >= 10) l1.next.val += 1;
if (l2.next == null) l2.next = new ListNode(0);
resList.next = Solution2(l1.next,l2.next);
return resList;
}
}
代码一下子简洁很多,但是速度反而没有代码1快,不能忍,优化一下。
代码3:优化递归代码。
public static ListNode Solution3(ListNode l1, ListNode l2)
{
int sumNumber = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val);
bool sumBiggerThanTen = sumNumber >= 10;
ListNode resList = new ListNode(sumBiggerThanTen ? sumNumber % 10 : sumNumber);
if ((l1 == null || l1.next == null) && (l2 == null || l2.next == null) && !sumBiggerThanTen)
return resList;
else
{
if (sumBiggerThanTen && l1.next == null) l1.next = new ListNode(1);
else if (sumBiggerThanTen) l1.next.val += 1;
resList.next = Solution3(l1 == null ? null : l1.next, l2 == null ? null : l2.next);
return resList;
}
}
速度明显变快,主要优化的点:
1、减少对象创建,尤其是new ListNode(0) ,在堆中分配对象很慢
2、比较结果复用 sumBiggerThanTen = sumNumber >= 10;