题库:https://leetcode-cn.com/problems/add-two-numbers/
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
import org.junit.Test; /** * 2 两数相加 * 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 * 请你将两个数相加,并以相同形式返回一个表示和的链表。 * 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。 * * 示例 1: * 输入:l1 = [2,4,3], l2 = [5,6,4] * 输出:[7,0,8] * 解释:342 + 465 = 807. * * @author zj * */ public class Solution2 { @Test public void method() { Node node1 = addTwoNumbers(build11(), build12()); printNode(node1); System.out.println(); Node node2 = addTwoNumbers(build21(), build22()); printNode(node2); } //打印链表 public void printNode(Node node) { while(null != node) { if(null == node.next) { //链表的当前节点的下一个节点为空,或者理解为最后一个节点 System.out.print(node.val); }else { //链表当前节点的下一个节点不为空,或者理解为不是最后一个节点 System.out.print(node.val + "-->"); } //获取下一个节点 node = node.next; } } //创建第一个链表 public Node build11() { Node node1 = new Node(2); Node node2 = new Node(4); Node node3 = new Node(3); node2.addNode(node3); node1.addNode(node2); return node1; } //创建第二个链表 public Node build12() { Node node1 = new Node(5); Node node2 = new Node(6); Node node3 = new Node(4); node2.addNode(node3); node1.addNode(node2); return node1; } public Node build21() { Node node1 = new Node(9); Node node2 = new Node(9); Node node3 = new Node(9); Node node4 = new Node(9); Node node5 = new Node(9); Node node6 = new Node(9); Node node7 = new Node(9); node6.addNode(node7); node5.addNode(node6); node4.addNode(node5); node3.addNode(node4); node2.addNode(node3); node1.addNode(node2); return node1; } public Node build22() { Node node1 = new Node(9); Node node2 = new Node(9); Node node3 = new Node(9); Node node4 = new Node(9); node3.addNode(node4); node2.addNode(node3); node1.addNode(node2); return node1; } /** * 两个链表相加 * 两个链表相加,可以理解为剥洋葱, * 计算第一个值放在洋葱的最外一层,计算第二个值放在洋葱的最外第二层。。。 * 但是想要的结果为整个洋葱,所以就需要两个链表进行收集计算值, * 一个链表作为想要的结果链表,一个链表为剥开的洋葱链表 * @param node1 * @param node2 * @return */ public Node addTwoNumbers(Node node1, Node node2) { if(null == node1) { return node2; } if(null == node2) { return node1; } //作为返回的洋葱 Node result =null; //作为将要剥开的洋葱 Node temp = null; //进位值 int carry = 0; //只要有一个链表不为空,就继续剥(遍历) while(null != node1 || null != node2) { //第一遍:获取第一个链表的第一个值 //第二遍:获取第一个链表的第二个值 int val1 = ((null != node1) ? node1.val : 0); //第一遍:获取第二个链表的第一个值 //第二遍:获取第二个链表的第二个值 int val2 = ((null != node2) ? node2.val : 0); //第一遍:计算两个链表的第一个值之和(此时carry为0) //第二遍:计算两个链表的第二个值之和(此时carry为0) int sum = val1 + val2 + carry; if(null == result) { //第一遍时:返回的洋葱为空,将要剥开的洋葱也是空, // 那么将计算结果存储在两个洋葱中,或者可以理解为初始化 temp = new Node(sum % 10); result = temp; }else { //第二遍:将结果值存储到剥开洋葱的第二层(temp为第一层) temp.next = new Node(sum % 10); //第二遍:获取剥开洋葱的第二层 temp = temp.next; } //第一遍:获取进位值(sum=2+5),不进位 //第二遍:获取进位值(sum=4+6),进位1 carry = sum / 10; if(null != node1) { //第一遍:获取第一个链表的第二个值,为下一循环做准备 //第二遍:获取第一个链表的第三个值,为下一循环做准备 node1 = node1.next; } if(null != node2) { //第一遍:获取第二个链表的第二个值,为下一循环做准备 //第二遍:获取第二个链表的第三个值,为下一循环做准备 node2 = node2.next; } if(carry > 0) { //第二遍:将要剥开的洋葱的下一层(temp为第二层,temp.next为第三层) temp.next = new Node(carry); } } return result; } class Node{ int val; Node next; public Node() {} public Node(int val) { this.val = val; } //添加节点 public void addNode(Node t) { //当前节点的下一节点 this.next = t; } } }