单链表反转&2个数字单链表相加

单链表反转


单链表是常用的数据结构,在开发中经常使用,我们现在来实现单链表的反转。

    private class Node<T> {
        public Node<T> next;
        public T v;

        public Node(T v) {
            this.v = v;
            next = null;
        }
    }

    /**
     * 链表反转
     *
     * @param head
     * @return
     */
    public static Node reverse(Node head) {
        if (head == null) {
            return null;
        }
        Node tmp = null;
        Node prev = null;
        while (head != null) {
            tmp = head.next;
            head.next = prev;
            prev = head;
            head = tmp;
        }
        return prev;
    }

数字链表相加


给定两个非空链表,每一个节点代表一个数字0-9,单个链表从左往右是由高位到低位组成的一个数,现在需要将两个链表表示的数相加并且以链表形式返回。
举例:Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 8 -> 0 -> 7
可不可以不采用逆序的方式实现?

(leetcode 445. 两数相加 II)

链表反转来实现相加

我们可以用链表反转的方法实现两个链表相加:

    /**
     * 量数字的链表相加  leetcode 445
     *
     * @param node1
     * @param node2
     * @return
     */
    public static Node addTwoNum(Node node1, Node node2) {
        Node l1 = reverse(node1);
        Node l2 = reverse(node2);
        Node head = new Node(0);
        Node tmp = head;
        int v1, v2, carry = 0, sum;
        while (l1 != null || l2 != null) {
            v1 = l1 != null ? l1.v : 0;
            v2 = l2 != null ? l2.v : 0;
            sum = carry + v1 + v2;
            carry = sum / 10;
            tmp.next = new Node(sum % 10);
            tmp = tmp.next;
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
        if (carry == 1) {
            tmp.next = new Node(1);
        }
        return reverse(head.next);
    }
逻辑解析:
  1. 首先反转两个链表,反转后,链表变为由低位到高位的排序。
  2. 然后从低位依次开始相加,如果有进位也需要计算进来,计算结果生成一个新的单链表。
  3. 最后,如果最大位计算结果,有进位,则需要新链表新增一个节点,节点是1(因为不可能大于1)。
  4. 最后将新链表反转,返回。

使用Stack来实现相加

    /**
     * 量数字的链表相加  leetcode 445
     *
     * @param node1
     * @param node2
     * @return
     */
    public static Node addTwoNum(Node node1, Node node2) {
        Node l1 = node1, l2 = node2;
        Stack<Node> s1 = new Stack();
        Stack<Node> s2 = new Stack();
        int n1 = 0, n2 = 0;
        while (l1 != null || l2 != null) {
            if (l1 != null) {
                s1.push(l1);
                l1 = l1.next;
                n1++;
            }
            if (l2 != null) {
                s1.push(l2);
                l2 = l2.next;
                n2++;
            }
        }
        int carry = 0;//进位符
        Node tmp1 = null, tmp2 = null;
        int v1, v2, sum;
        if (n1 > n2) {
            while (!s1.isEmpty()) {
                tmp1 = s1.pop();
                v2 = s2.isEmpty() ? 0 : s2.pop().v;
                sum = tmp1.v + v2 + carry;
                carry = sum / 10;
                tmp1.v = sum % 10;
            }
            if (carry == 1) {
                Node node = new Node(1);
                node.next = node1;
                return node;
            } else {
                return node1;
            }
        } else {
            while (!s2.isEmpty()) {
                tmp2 = s2.pop();
                v1 = s1.isEmpty() ? 0 : s1.v;
                sum = tmp2.v + v1 + carry;
                carry = sum / 10;
                tmp2.v = sum % 10;
            }
            if (carry == 1) {
                Node node = new Node(1);
                node.next = node2;
                return node;
            } else {
                return node2;
            }
        }
    }
逻辑解析:
  1. 首先创建2个Stack,并将两个链表中的数据分别存储到2个栈中。
  2. 因为栈有后进先出的特性,所以,这里相当于链表内容进行了反转,最小位数的值在栈顶。
  3. 分别计算出两个链表的长度,当链表1长时,我们的返回值是链表1,当链表2长时,我们的返回值是链表2(当然每个节点都是数值相加后的)。
  4. 栈依次弹出节点,然后节点相加,将结果赋值给链表长度较长的那个链表对应节点。
  5. 最后如果有进位,则创建一个新的节点,作为头,返回即可,如果没有进位,直接返回对应链表。

猜你喜欢

转载自blog.csdn.net/u011578734/article/details/106387139