ARTS打卡第六周

Algorithm: Leetcode 445. 两数相加 II

题目描述:
You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Follow up:
What if you cannot modify the input lists? In other words, reversing the lists is not allowed.

Example:

Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 8 -> 0 -> 7

解法一:
两个list的长度可能不一样,先用0补齐,再递归。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int len1 = 0;
        for(ListNode p = l1; p != null; p = p.next, len1++);
        int len2 = 0;
        for(ListNode p = l2; p != null; p = p.next, len2++);
        
        if(len1 > len2) {
            for(int i=0; i < len1-len2; i++) {
                ListNode p = new ListNode(0);
                p.next = l2;
                l2 = p;
            }
        } else if(len1 < len2) {
            for(int i=0; i < len2-len1; i++) {
                ListNode p = new ListNode(0);
                p.next = l1;
                l1 = p;
            }
        }
        
        ListNode ans = new ListNode(0);
        int c = add(l1, l2, ans);
        if(c != 0) {
            ListNode p = new ListNode(c);
            p.next = ans;
            ans = p;
        }
        return ans;
        
    }
    
    public int add(ListNode a, ListNode b, ListNode result) {
        int sum = 0;
        if(a.next == null && b.next == null) {
            sum  = a.val + b.val;
        } else {
           result.next = new ListNode(0);
            sum = a.val + b.val + add(a.next, b.next, result.next); 
        }
        result.val = sum % 10;
        return sum / 10;
    }
}

解法二:将输入反转,链表的开头变成最低位,从最低位开始,逐位相加,最后把结果反转。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        l1 = reverse(l1);
        l2 = reverse(l2);
        return addTwoNumbers1(l1, l2);
    }
    private ListNode reverse(ListNode l) {
        if(l == null) {
            return null;
        }
        
        ListNode p1 = l;
        ListNode p2 = p1.next; // nullable
        ListNode p3 = p2 == null ? null : p2.next; // nullable
        
        p1.next = null;
        while(p2 != null) {
    
            p2.next = p1;
            
            p1 = p2;
            p2 = p3;
            p3 = p3 == null ? null : p3.next;
        }
        return p1;
    }
    
    private ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
        if(l1 == null) {
            return l2;
        }
        if(l2 == null) {
            return l1;
        }
        
        ListNode result = new ListNode(0);
        ListNode p = result;
        int carry = 0;
        while(l1 != null || l2 != null || carry != 0) {
            int sum = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val) + carry;
            carry = sum / 10;
            p.next = new ListNode(sum % 10);
            p = p.next;
            l1 = l1 == null ? null : l1.next;
            l2 = l2 == null ? null : l2.next;
        }
        result = result.next;
        return reverse(result);
    }
}

解法三:不改变输入,用栈(或LinkedList)保存输入,利用栈后进先出的特点,从低位开始加,最后将结果反转。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<Integer> s1 = pushToStack(l1);
        Stack<Integer> s2 = pushToStack(l2);
        int carry = 0;
        ListNode result = new ListNode(0);
        ListNode p = result;
        while(!s1.empty() || !s2.empty() || carry != 0) {
            int a = s1.empty() ? 0 : s1.pop();
            int b = s2.empty()? 0 : s2.pop();
            int sum = a + b + carry;
            p.next = new ListNode(sum % 10);
            p = p.next;
            carry = sum / 10;
        }
        return reverse(result.next);
        
    }
    
    private Stack<Integer> pushToStack(ListNode l1) {
        Stack<Integer> s1 = new Stack<>();
        while(l1 != null) {
            s1.push(l1.val);
            l1 = l1.next;
        }
        return s1;
    }
    
    private ListNode reverse(ListNode l) {
        if(l == null) {
            return null;
        }
        
        ListNode p1 = l;
        ListNode p2 = p1.next; // nullable
        ListNode p3 = p2 == null ? null : p2.next; // nullable
        
        p1.next = null;
        while(p2 != null) {
    
            p2.next = p1;
            
            p1 = p2;
            p2 = p3;
            p3 = p3 == null ? null : p3.next;
        }
        return p1;
    }
}

三种解法中,反转输入的链表是最快的。

Review:EaaS: Everything-as-a-Service

文章阐述了传统的服务和现在流行的SOA、微服务等各自的特点,抛出了未来“万物都是服务”这么一个论点。

文中阐述了SOA和微服务架构的共同点和主要的区别。首先,两种的共同点是都秉承了模块化的设计理念:高内聚、低耦合。不同点:SOA主要是在应用层面实现模块化,而数据库等组建还是共用的。而微服务则是每个组建都独立,一个微服务实例从上到下自成一体。

文章后面还介绍了IaaS、Paas、SaaS等概念,用一张图清晰地展示了这些不同“服务”之间的区别。
[外链图片转存失败(img-XHW0ntDs-1562044526151)(https://cdn-images-1.medium.com/max/800/1*OIXF4l8XLNTkOcdSVuX65Q.png)]

Tip:

在用hibernate的ORM时,如果A类和B类之间通过@ManyToOne关联,当持久化A类时,要求B类先持久化,否则会报错:

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing 

即数据库里面要先有One后有Many,因为ManyToOne实际上是一个外键约束。

Share:关于HashMap容量的初始化,还有这么多学问

HashMap的构造方法支持传入初始容量,但是并不是直接将元素个数作为初始容量就OK了。

HashMap并不一定采用我们传入的初始容量,而是寻找一个大于它且最接近的2的N次幂。并且,HashMap中有个负载因子(loadFactor),默认值是0.75,意思是当map中的元素个数达到 当前容量负载因子 时,就会发生扩容。举个例子,我们的元素个数是16,当我们把初始容量设为16时,元素个数达到 160.75=12 个时,就会发生扩容,这显然不是我们想要的。我们需要将初始容量设为
16 / 0.75 + 1 = 22 才能保证所有元素都放进map并且不会发生扩容(当然了,jdk不会直接使用22,而是会向上寻找最近的2的N次幂,也就是32)。

在实际使用时,对于我们能够确切知道元素个数的情况下,尤其是在一些性能敏感的场景下,或者是在循环体内部,尽量计算好合适的初始容量,避免扩容带来性能损失。
Google的guava 21版本之后的集合工具类都提供了类似这样的api

Maps.newHashMapWithExpectedSize(int expectedSize)

我们只要传入实际的元素个数就行了,内部会完成上述计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值