445. 两数相加II

翻转链表

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        l1 = reverseList(l1);
        l2 = reverseList(l2);

        /**
         * 最后还要反转一下
         */
        return reverseList(addNumbers(l1, l2));
    }

    /**
     * 先反转两个链表
     */
    public ListNode reverseList(ListNode head) {

        ListNode prev = null;
        ListNode curr = head;

        while (curr != null) {

            ListNode tem = curr.next;
            curr.next = prev;
            prev = curr;
            curr = tem;
        }

        return prev;
    }

    /**
     * 转换为逆序后再相加
     */
    public ListNode addNumbers(ListNode l1, ListNode l2) {

        ListNode dummyHead = new ListNode(-1);
        ListNode head = dummyHead;
        ListNode cur1 = l1;
        ListNode cur2 = l2;

        int n;
        int sum;
        int rest = 0;

        while (cur1 != null || cur2 != null){

            sum = (cur1 == null ? 0 : cur1.val) + (cur2 == null ? 0 : cur2.val) + rest;

            n = sum % 10;
            rest = sum / 10;

            head.next = new ListNode(n);
            head = head.next;

            if (cur1 != null){
                cur1 = cur1.next;
            }

            if (cur2 != null){
                cur2 = cur2.next;
            }
        }

        if (rest == 1){
            head.next = new ListNode(rest);
        }

        return dummyHead.next;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 */

不翻转链表——用栈存储

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        /**
         * 将两个链表压入栈中,这样出栈时的顺序就是《2. 两数相加》
         * 最后将结果也要存入栈中,打印的顺序就是从高位到低位
         */
        Stack<Integer> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        Stack<Integer> stack = new Stack<>();
        ListNode dummyHead = new ListNode(-1);
        ListNode head = dummyHead;

        ListNode cur1 = l1;
        ListNode cur2 = l2;

        while (cur1 != null){

            stack1.push(cur1.val);
            cur1 = cur1.next;
        }

        while (cur2 != null){

            stack2.push(cur2.val);
            cur2 = cur2.next;
        }

        int sum;
        int n;
        int rest = 0;

        while (!stack1.empty() || !stack2.empty()){

            sum = (stack1.empty() ? 0 : stack1.pop()) + (stack2.empty() ? 0 : stack2.pop()) + rest;

            n = sum % 10;
            rest = sum / 10;

            stack.push(n);
        }

        if (rest != 0){
            stack.push(rest);
        }

        while (!stack.empty()){

            head.next = new ListNode(stack.pop());
            head = head.next;
        }

        return dummyHead.next;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */

优化1——加和时动态翻转链表

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        /**
         * 将两个链表压入栈中,这样出栈时的顺序就是《2. 两数相加》
         * 可以在存储结果时就翻转链表,这样就不用再使用栈来存储
         */
        Stack<Integer> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        ListNode prev = null;

        ListNode cur1 = l1;
        ListNode cur2 = l2;

        while (cur1 != null){

            stack1.push(cur1.val);
            cur1 = cur1.next;
        }

        while (cur2 != null){

            stack2.push(cur2.val);
            cur2 = cur2.next;
        }

        int sum;
        int n;
        int rest = 0;

        /**
         * 只要有一个链表还有元素,或者进位数不为0,循环就继续
         * 将最后的rest == 1的情况合并到循环中
         */
        while (!stack1.empty() || !stack2.empty() || rest != 0){

            sum = (stack1.empty() ? 0 : stack1.pop()) + (stack2.empty() ? 0 : stack2.pop()) + rest;

            n = sum % 10;
            rest = sum / 10;

            /**
             * 存储结果时就翻转链表,最后一个节点始终是头节点
             */
            ListNode cur = new ListNode(n);
            cur.next = prev;
            prev = cur;
        }

        return prev;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */

https://leetcode-cn.com/problems/add-two-numbers-ii/

posted @ 2021-12-10 10:37  振袖秋枫问红叶  阅读(34)  评论(0)    收藏  举报