兩個數相加。
題目:
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;