2 两数相加

题库: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;
        }
    }
}

 

posted @ 2021-11-23 20:32  ASKANDANSWERS  阅读(63)  评论(1编辑  收藏  举报