LeetCode-2.两数相加
题目
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807
解法
package com.zhen.leetCode.middle; /** * 两数相加 * * 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 * * * @author Din * */ public class AddTwoNumbers { static class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public static void main(String[] args) { //测试用例1 ListNode l1 = new ListNode(2); ListNode l11 = new ListNode(4); ListNode l12 = new ListNode(3); l11.next = l12; l1.next = l11; ListNode l2 = new ListNode(5); ListNode l21 = new ListNode(6); ListNode l22 = new ListNode(4); l21.next = l22; l2.next = l21; //测试用例2 ListNode l3 = new ListNode(1); ListNode l31 = new ListNode(8); l3.next = l31; ListNode l4 = new ListNode(0); ListNode resultNode = addTwoNumbers(l1, l2); while(null != resultNode) { System.out.println(resultNode.val); resultNode = resultNode.next; } } /** * 解法一:递归 * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { if (null == l1 && null == l2) { return null; } //算出两值和 int sumVal = 0; if (null != l1) { sumVal += l1.val; } if (null != l2) { sumVal += l2.val; } //当前node新值 int newVal = sumVal > 9 ? sumVal - 10 : sumVal; //下个node需要添加的值 int addVal = sumVal > 9 ? 1 : 0; //返回新listNode ListNode resultNode = new ListNode(newVal); ListNode nextNode = null; ListNode next1 = null; ListNode next2 = null; if (null != l1 && null != l1.next) { l1.next.val += addVal; }else if(null != l2 && null != l2.next) { l2.next.val += addVal; }else { //l1\l2都为空 if (addVal > 0) { nextNode = new ListNode(addVal); } } if (null != l1) { next1 = l1.next; } if (null != l2) { next2 = l2.next; } if (null != next1 || null != next2) { nextNode = addTwoNumbers(next1, next2); } resultNode.next = nextNode; return resultNode; } /** * 解法二:遍历到两个node都为空 * 伪代码如下: 将当前结点初始化为返回列表的哑结点。 将进位 carry 初始化为 0。 将 p 和 q 分别初始化为列表 l1 和 l2 的头部。 遍历列表 l1 和 l2 直至到达它们的尾端。 将 x 设为结点 p 的值。如果 p 已经到达 l1 的末尾,则将其值设置为 0。 将 y 设为结点 q 的值。如果 q 已经到达 l2 的末尾,则将其值设置为0。 设定 sum = x + y + carry。 更新进位的值,carry = sum / 10。 创建一个数值为(sum mod 10) 的新结点,并将其设置为当前结点的下一个结点,然后将当前结点前进到下一个结点。 同时,将 p 和 q 前进到下一个结点。 检查 carry = 1 是否成立,如果成立,则向返回列表追加一个含有数字 11 的新结点。 返回哑结点的下一个结点。 时间复杂度:O(max(m,n)),假设 mm 和 nn 分别表示 l1和 l2 的长度,上面的算法最多重复 max(m,n) 次。 空间复杂度:O(max(m,n)), 新列表的长度最多为 max(m,n)+1。 * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbers1(ListNode l1, ListNode l2) { ListNode dummyHead = new ListNode(0); ListNode p = l1, q = l2, curr = dummyHead; int carry = 0; while (p != null || q != null) { int x = (p != null) ? p.val : 0; int y = (q != null) ? q.val : 0; int sum = carry + x + y; carry = sum / 10; curr.next = new ListNode(sum % 10); curr = curr.next; if (p != null) p = p.next; if (q != null) q = q.next; } if (carry > 0) { curr.next = new ListNode(carry); } return dummyHead.next; } }
done.