算法-求和问题
1. 两个List表示的数字求和
说明:给定两个「非空」链表,「逆序」存储两个「非负」整数,每个节点仅存储「一位」数字,除了数字 0 以外都不会以 0 开头,请以相同方式返回一个新的链表,表示两个数的和。
例 1:
[2 -> 4 -> 3] + [5 -> 6 -> 4] = [7 -> 0 -> 8]
题解:342 + 465 = 807
列表节点的数据结构为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class ListNode { int val; ListNode next;
ListNode() { } ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } }
|
1.1 循环解法
由于题目给出链表是「逆序」,因此头部节点表示的是实际数字的末位,所以可以直接从两个链表的头部节点开始循环,逐个节点位移,每次都对两个链表同一位的节点求和,并判断进位,如果其中一个链表已经结束,则可以视其对应位的值为 0,直到两个链表都已结束。
注意:对两个链表按位遍历求和结束后,还需要对最终结果判断一次进位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| class Solution_Loop { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode result = new ListNode(); ListNode resultNext = null; boolean needAdd = false; int sum; while (l1 != null || l2 != null) { if (resultNext == null) { resultNext = result; } else { resultNext.next = new ListNode(); resultNext = resultNext.next; } sum = getVal(l1) + getVal(l2); if (needAdd) { sum++; } if (sum > 9) { sum %= 10; needAdd = true; } else { needAdd = false; } resultNext.val = sum; if (l1 != null) { l1 = l1.next; } if (l2 != null) { l2 = l2.next; } } if (resultNext == null) { resultNext = result; } if (needAdd) { resultNext.next = new ListNode(1); } return result; }
private int getVal(ListNode node) { return (node == null) ? 0 : node.val; } }
|
1.2 递归解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution_Recursion { private boolean needAdd = false;
public ListNode addTwoNumbers(ListNode l1, ListNode l2) { if (l1 == null && l2 == null && !needAdd) { return null; } int sum = getVal(l1) + getVal(l2) + (needAdd ? 1 : 0); needAdd = (sum / 10) > 0; ListNode next = new ListNode(sum %= 10); next.next = addTwoNumbers((l1 == null ? null : l1.next), (l2 == null ? null : l2.next)); return next; }
private int getVal(ListNode node) { return (node == null) ? 0 : node.val; } }
|
2. 大数相加