美文网首页
leetcode算法—两数相加(中等)

leetcode算法—两数相加(中等)

作者: 小胖学编程 | 来源:发表于2021-07-08 20:43 被阅读0次

    leetcode的两数相加

    image.png

    1. 总结

    开始使用迭代实现后,后续使用的递归实现。

    1.1 遇到的坑

    1. 想要删除链表中的节点,必须持有该节点的上一个节点。若只知道待删除节点的引用,是无法在链表中删除的。
    image.png

    1.2 获得的经验

    1. 链表的整数运算中,除10表示进的位数,取余10表示剩余的位数。
    2. 递归就是分治,需要递归出口,以及最终使用分-治,还是治-分;
      2.1 分-治:即先执行递归方法,而后执行业务操作;
      2.2 治-分:先执行业务操作,再执行递归方法;
      分析题目可知,需要从链表头进行计算,故先进行“治”再“分”。
    3. 因为链表单向性,要善于使用引用保存链表的起始位置;

    1.3 得到教训

    链表操作时,为了不失去去尾节点的控制,最好每次迭代/递归返回上一个节点的引用。

    2. 代码实现

    public class ListNode {
        int val;
        ListNode next;
    
        ListNode() {
        }
    
        ListNode(int val) {
            this.val = val;
        }
    
        ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
        }
    }
    

    2.1 迭代实现

    class Solution {
        /**
         * 引用的问题
         * 1. 链表中,持有的是尾结点对象的引用,将引用置为空。
         * 但是尾结点对象依旧存在,若是让尾节点在链表中设置为空,要获取到尾节点的上一个节点引用,将其从链中删除
         * <p>
         * <p>
         * 解答成功:
         * 执行耗时:2 ms,击败了99.98% 的Java用户
         * 内存消耗:38.6 MB,击败了80.31% 的Java用户
         */
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    
            ListNode result = new ListNode();
            result.next = new ListNode();
            ListNode r1 = result.next;
    
            //均不为空的情况
            int x1 = 0;
            while (l1 != null || l2 != null) {
                int v1 = l1 != null ? l1.val : 0;
                int v2 = l2 != null ? l2.val : 0;
                int x = v1 + v2 + x1;
                int x2;
                if (x != 0) {
                    //需要进的位数
                    x1 = x / 10;
                    //自己需要存储的位数
                    x2 = x % 10;
                } else {
                    x1 = 0;
                    x2 = 0;
                }
                result = result.next;
                result.val = x2;
                result.next = new ListNode();
                //持有对象
                l1 = l1 != null ? l1.next : null;
                l2 = l2 != null ? l2.next : null;
            }
            if (x1 != 0) {
                result.next.val = x1;
            } else {
                result.next = null;
            }
            return r1;
        }
    }
    

    2.2 递归实现

    每次递归前,节点指向下一节点,但是递归方法中传递的是本节点。当尾节点的val为0时,因为拿到的尾节点上一个节点的引用,是可以删除尾结点的。

    class Solution {
    
        /**
         * 解答成功:
         * 执行耗时:2 ms,击败了99.98% 的Java用户
         * 内存消耗:38.6 MB,击败了78.95% 的Java用户
         * <p>
         * 递归-分治
         * <p>
         * 该逻辑需要先治再分。先执行逻辑,然后再递归
         * 1. 递归出口
         * 2. 中间逻辑
         * <p>
         * [0,0]
         */
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    
            ListNode listNode = new ListNode();
            listNode.next = new ListNode();
            ListNode r = listNode.next;
            addTwoNumber(l1, l2, 0, listNode);
            return r;
        }
    
        /**
         * 1. 若想删除链表中的节点,必须知道上一个节点的引用,
         * 若只知道本节点引用是无法删除链表中节点;
         * <p>
         * 2. 递归  -  分治    治分
         * <p>
         * 3. 链表的整数运算中,除表示进的位数,取余表示剩余的位数。
         */
        private ListNode addTwoNumber(ListNode l1, ListNode l2, int x2, ListNode result) {
            //递归出口
            if (l1 == null && l2 == null) {
                if (x2 != 0) {
                    result.next.val = x2;
                } else {
                    result.next = null;
                }
                return result;
            }
            int v1 = l1 != null ? l1.val : 0;
            int v2 = l2 != null ? l2.val : 0;
    
            int t = v1 + v2 + x2;
            x2 = t / 10;
            int x1 = t % 10;
    
            //赋值
            result = result.next;
    
            result.val = x1;
            result.next = new ListNode();
            return addTwoNumber(l1 != null ? l1.next : null, l2 != null ? l2.next : null, x2, result);
        }
    }
    

    相关文章

      网友评论

          本文标题:leetcode算法—两数相加(中等)

          本文链接:https://www.haomeiwen.com/subject/grytpltx.html