Coder Social home page Coder Social logo

android_interview's Issues

重建二叉树的问题

大佬,谢谢你能整理出这么好的资料,但是我在看重建二叉树的的那个面试题的答案的时候,我发现重建的二叉树和原本的二叉树完全不一样,虽然输出的的结果一样,但是结构不一样
image

NET::ERR_CERT_DATE_INVALID

NET::ERR_CERT_DATE_INVALID
Subject: *.gitbooks.io

Issuer: Go Daddy Secure Certificate Authority - G2

Expires on: 2018年9月9日

Current date: 2018年11月19日

PEM encoded chain:
-----BEGIN CERTIFICATE-----
MIIFLTCCBBWgAwIBAgIJAK8gzpzuEJmjMA0GCSqGSIb3DQEBCwUAMIG0MQswCQYD
VQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEa
MBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0
cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2Vj
dXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTE3MDkwOTEwMDUwMFoX
DTE4MDkwOTEwMDUwMFowOzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRh
dGVkMRYwFAYDVQQDDA0qLmdpdGJvb2tzLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAxjy2ZpDtcsgdt8W89c5xJbtUyEscUBMtoC4Tkj6zyMOVjoyF
HqUlFsyictbbuUlcxqWii4s5UvaqT1bC7Wgm5ea+8IGoCXaahih41eAuZJ7Kzb1W
PzlISgqrKL1GGT/nrOC/w+459KuZZUnEA6lx22r2ThwNqQW8y+vYKvHCHpGqTNha
/wKM9SJE77EqiSNl9DC0t2THfSadgygOyvH1RRLTcffcuQ28TknUJMFl6mFG2K6n
ll1sZ8xL0LS9mPnKMWcZd0uD1Nh95k1Tt52PMB0AlWYchJc01hBK5/99I2/zf+vQ
l1Ddywgq2UabbesYJUEwf3bQOPEwxeVGXViHBwIDAQABo4IBuDCCAbQwDAYDVR0T
AQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/
BAQDAgWgMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly9jcmwuZ29kYWRkeS5jb20v
Z2RpZzJzMS02ODkuY3JsMF0GA1UdIARWMFQwSAYLYIZIAYb9bQEHFwEwOTA3Bggr
BgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0
b3J5LzAIBgZngQwBAgEwdgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRw
Oi8vb2NzcC5nb2RhZGR5LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jZXJ0aWZp
Y2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZGlnMi5jcnQwHwYDVR0jBBgw
FoAUQMK9J47MNIMwojPX+2yz8LQsgM4wJQYDVR0RBB4wHIINKi5naXRib29rcy5p
b4ILZ2l0Ym9va3MuaW8wHQYDVR0OBBYEFLc2RmeZePdeA2SZoYpg9eUJh43yMA0G
CSqGSIb3DQEBCwUAA4IBAQCOJ5mXJIKhACPLjqfpRa1lxWy1KDe0Ws/MQEtvNTQC
PTevBP/NdP5QRLWju850OdrNG0gDceI9Kk37ztkVVkWLR5m8/n60K5rUtOJ5x6ew
lkgtuI6aD3dViLPjpFTQ5myHE2Jd01qmm98o7H0Wp1c878d7sFHyHuc6QtjinR+3
yuthNKNspxaPDTPnWg8jjIcod9iRZcc67Wj3kB/oIRHlQz97QTAnCKMDcpHccAcn
WlvUuq0LTK66R6q4MTABhu/HRwie1Fb9dgDUQVEqtzx4gvomcHJq9I+7UWHla0aj
gofutXKNMEzffElCxSvFMtTqPcpvCYd6CwK9EZYnPyjI
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAwMFoXDTMxMDUwMzA3
MDAwMFowgbQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UE
CxMkaHR0cDovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQD
EypHbyBEYWRkeSBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC54MsQ1K92vdSTYuswZLiBCGzD
BNliF44v/z5lz4/OYuY8UhzaFkVLVat4a2ODYpDOD2lsmcgaFItMzEUz6ojcnqOv
K/6AYZ15V8TPLvQ/MDxdR/yaFrzDN5ZBUY4RS1T4KL7QjL7wMDge87Am+GZHY23e
cSZHjzhHU9FGHbTj3ADqRay9vHHZqm8A29vNMDp5T19MR/gd71vCxJ1gO7GyQ5HY
pDNO6rPWJ0+tJYqlxvTV0KaudAVkV4i1RFXULSo6Pvi4vekyCgKUZMQWOlDxSq7n
eTOvDCAHf+jfBDnCaQJsY1L6d8EbyHSHyLmTGFBUNUtpTrw700kuH9zB0lL7AgMB
AAGjggEaMIIBFjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
HQ4EFgQUQMK9J47MNIMwojPX+2yz8LQsgM4wHwYDVR0jBBgwFoAUOpqFBxBnKLbv
9r0FQW4gwZTaD94wNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v
b2NzcC5nb2RhZGR5LmNvbS8wNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5n
b2RhZGR5LmNvbS9nZHJvb3QtZzIuY3JsMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEG
CCsGAQUFBwIBFiVodHRwczovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv
MA0GCSqGSIb3DQEBCwUAA4IBAQAIfmyTEMg4uJapkEv/oV9PBO9sPpyIBslQj6Zz
91cxG7685C/b+LrTW+C05+Z5Yg4MotdqY3MxtfWoSKQ7CC2iXZDXtHwlTxFWMMS2
RJ17LJ3lXubvDGGqv+QqG+6EnriDfcFDzkSnE3ANkR/0yBOtg2DZ2HKocyQetawi
DsoXiWJYRBuriSUBAA/NxBti21G00w9RKpv0vHP8ds42pM3Z2Czqrpv1KrKQ0U11
GIo/ikGQI31bS/6kA1ibRrLDYGCD+H1QQc7CoZDDu+8CL9IVVO5EFdkKrqeKM+2x
LXY2JtwE65/3YR8V3Idv7kaWKK2hJn0KCacuBKONvPi8BDAB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
4uJEvlz36hz1
-----END CERTIFICATE-----

是我被 DNS 污染了还是真的证书过期了,访问其它 GitBooks 不会出现这个问题。

树的前驱和后继中,代码是否有误

// 如果x没有左孩子。则x有以下两种可能:
// (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
// (02) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
BSTNode y = x.parent;
while ((y!=null) && (x==y.left)) {
x = y;
y = y.parent;
}

上面提到“x的最低的父结点,并且该父结点要具有右孩子”
while ((y!=null) && (x==y.left)) { // y是x的父节点, x是y的左孩子
也就是符合第二点 ,但是好像没有判断该父节点是否具有右孩子。

Activity启动模式中的Android 5.0之后跨应用启动Activity,会加入新的Task中错误

首先不得不说,网上好多资料是虚假的。。。有些地方还是需要自己验证下,而且这个错误,竟然能搜到好多相关的网页,都是按照这个错误来说明的!!!!这种胡说八道的传播的也太广了吧 。。。
Activity启动模式中的Android 5.0之后跨应用启动Activity,会加入新的Task中错误, 还是同一个任务栈,并且近期任务中也不会显示成两个,还是一个 !!!!

LruCache错误

get的时候应该是把元素移到队尾,队头的才是最少使用的元素,所以当内存满的时候是把队头的元素删除。(//迭代器获取第一个对象,即队尾的元素,近期最少访问的元素。 Map.Entry<K, V> toEvict = map.entrySet().iterator().next();)这个获取到的是队头元素来的。

求个一个gitbook的地址

@LRH1993 你好,我之前实在gitbook上看的 并不是在github上看的
有个gitbook的地址 我给弄不见了 感觉看起来像看书那种的
谢谢

内容纠错

3.1.1 Activity全方位解析
2.特殊情况下的生命周期
①横竖屏切换
...并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象参数同时传递给onSaveInstanceState和onCreate方法...

是不是应该改为
...并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象参数同时传递给onRestoreInstanceState和onCreate方法...

Android 缓存策略的文章。引用ruheng的那篇的LRUCache 原理错了。

LruCache的核心**很好理解,就是要维护一个缓存对象列表,其中对象列表的排列方式是按照访问顺序实现的,即一直没访问的对象,将放在队尾,即将被淘汰。而最近访问的对象将放在队头,最后被淘汰。

这是错的,应该是 访问的放到队尾,新添加的元素也放到队尾,删除是从队首 删除的。另外图解也是错的。请纠正,以免误导后来的读者。

DoubleLink

您好,非常感谢您在百忙之中能够抽出时间提交了这么好的文章,非常感谢.在我查看数据结构---线性表这篇文章的时候,发现您使用java实现双链表的逻辑中,发现了逻辑问题,如下是insert方法中后半部分的代码逻辑:
DNode inode = getNode(index);
//新插入的点 前驱为iNode的前驱 后继为inode
DNode tnode = new DNode(t, inode.prev, inode);
//修改inode前驱的后继
inode.prev.next = tnode;
//此句代码应该是修改inode的前驱 应为 inode.prev = tnode 而源码中是如下所示
inode.next = tnode;
mCount++;
return ;

//还望作者知悉,及时修改,再次感谢您在百忙之中能带来这么好的文章.

内容纠错

在java反射(一)中
通过Class对象的getMethods()方法或者getMethod()方法获得指定方法
应该改为
通过Class对象的getDeclaredMethods()方法或者getMethod()方法获得指定方法

生产者/消费者那篇文章,最后的多生产/多消费代码实现有点问题吧

原文是使用reentrantLock和condition来实现多生产,多消费模式,但是再开启多个线程的时候传入的是同一个condition,并不能控制多个线程

public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Condition newCondition = lock.newCondition();
        Product product = new Product(lock,newCondition);
        Consumer consumer = new Consumer(lock,newCondition);
        for(int i=0;i<3;i++){
            ThreadProduct pThread = new ThreadProduct(product);
            ThreadConsumer cThread = new ThreadConsumer(consumer);
            pThread.start();
            cThread.start();
        }

    }

这样运行的结果也有问题,会有两个线程get不到val
修改为

public static void main(String[] args){
        ReentrantLock lock = new ReentrantLock();
        for (int i=0;i<3;i++){   
            Condition condition = lock.newCondition();
            Producer producer = new Producer(lock,condition);
            Consumer consumer = new Consumer(lock,condition);
            ProducerThread producerThread = new ProducerThread(producer);
            ConsumerThread consumerThread = new ConsumerThread(consumer);
            producerThread.start();
            consumerThread.start();
        }
    }

就是每个线程里有一个condition,一个reentrantlock可以有多个condition。
结果正常

适配器模式中的 【对象适配器模式】Adapter 类,是否应该实现 Target 接口?

public class Adapter {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }
    /**
     * 源类Adaptee有方法sampleOperation1
     * 因此适配器类直接委派即可
     */
    public void sampleOperation1(){
        this.adaptee.sampleOperation1();
    }
    /**
     * 源类Adaptee没有方法sampleOperation2
     * 因此由适配器类需要补充此方法
     */
    public void sampleOperation2(){
        //写相关的代码
    }
}

是否改成这样?

public class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }

    /**
     * 源类Adaptee有方法sampleOperation1
     * 因此适配器类直接委派即可
     */
    @Override
    public void sampleOperation1(){
        this.adaptee.sampleOperation1();
    }

    /**
     * 源类Adaptee没有方法sampleOperation2
     * 因此由适配器类需要补充此方法
     */
    @Override
    public void sampleOperation2(){
        //写相关的代码
    }
}

建议

建议弄一个Android各个版本变更内容的模块,面试的时候也容易问到

volatile关键字章节的问题求解

volatile关键字章节中,有一段代码:

public class Test {
    public volatile int inc = 0;

    public void increase() {
        inc++;
    }

    public static void main(String[] args) {
        final Test test = new Test();
        for (int i = 0; i < 10; i++) {
            new Thread() {
                public void run() {
                    for (int j = 0; j < 1000; j++)
                        test.increase();
                }
            }.start();
        }

        while (Thread.activeCount() > 1)  //保证前面的线程都执行完
            Thread.yield();
        System.out.println(test.inc);
    }
}

我每次执行这段代码都没有结果,文章却说有结果,不是很明白。希望您能解答下。
我自己对代码进行了更正:

public class Nothing {

    private volatile int inc = 0;
    private volatile static int count = 10;

    private void increase() {
        ++inc;
    }

    public static void main(String[] args) {
        int loop = 10;
        Nothing nothing = new Nothing();
        while (loop-- > 0) {
            nothing.operation();
        }
    }

    private void operation() {
        final Nothing test = new Nothing();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000000; j++) {
                    test.increase();
                }
                --count;
            }).start();
        }

        // 保证前面的线程都执行完
        while (count > 0) {

        }
        System.out.println("最后的数据为:" + test.inc);
    }

}

这个在IDEA,JDK8中的显示结果和文章中的描述一致。

结果如下:

最后的数据为:5919956
最后的数据为:3637231
最后的数据为:2144549
最后的数据为:2403538
最后的数据为:1762639
最后的数据为:2878721
最后的数据为:2658645
最后的数据为:2534078
最后的数据为:2031751
最后的数据为:2924506

关于补间动画10%p含义的疑问

10%p 的含义是 距离动画所在view父控件左边缘的距离是整个view宽度的10% 可以理解为动画起始点的位置是在距离父控件左边缘的view宽度的10%吗? 但是从网上的的一些博客中有的是说, 其代表子控件左上角的坐标加上父控件宽度的10%,我也实验倾向后一种解释,您看对吗?

用命令导出PDF报错

warn: "options" property is deprecated, use config.get(key) instead
(node:17917) DeprecationWarning: Using Buffer without new will soon stop working. Use new Buffer(), or preferably Buffer.from(), Buffer.allocUnsafe() or Buffer.alloc() instead.
error: error while generating page "java/basis/Collections-Framework.md":

Error: getaddrinfo ENOTFOUND upload-images.jianshu.io upload-images.jianshu.io:80
➜ android_interview-master git:(master)

其他常见的树中

树的带权路径长度

定义:树的带权路径长度规定为所有叶子结点的带权路径长度之和

文章的例子的 “”树的WPL= 1100 + 280 + 320 + 310 = 100 + 160 + 60 + 30 = 350。”

他的叶子节点不是 100 50 20 10 吗 80是弄错了吧?

快速排序有错

int[] a = {50,1,2,8,44,5,632,23,345,3425,173,4,5,63,6,7};
我在测试快速排序时,使用了这个数组,结果在某个getMiddle()死循环了。应该是哪里出了问题。

剑指offer23题发现的问题

剑指offer23题这里,三个函数传入的是同一个head,这样有问题吧,cloneNodes(head);执行完,head就不是头节点了,再去执行 connectNodes(head);就错了。应给给一个临时变量cur,每个方法执行前赋值为head, 然后方法调用传入cur.
/**
* 实现函复制一个复杂链表。在复杂链表中,每个结点除了有一个next字段指向下一个结点外,
* 还有一个sibling字段指向链表中的任意结点或者NULL
*
* @param head 链表表头结点
* @return 复制结点的头结点
*/
public static ComplexListNode clone(ComplexListNode head) {
// 如果链表为空就直接返回空
if (head == null) {
return null;
}

    // 先复制结点
    cloneNodes(head);
    // 再链接sibling字段
    connectNodes(head);
    // 将整个链表拆分,返回复制链表的头结点
    return reconnectNodes(head);
}

Android 还值得卷嘛

越来越难了。 我18年校招, 凭借这个仓库,找到了校招的工作。 现在 24年, 6年过去了。还在看这个八股。
现在的Android 面试要求是越来越高了, 招聘也是萎缩了很多,大环境太差了

集合中关于Iterator的问题

下面这句话好像不太对吧。

**注意:**当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量(就如同参数传递是值传递,基本数据类型传递的是值,引用类型传递的仅仅是对象的引用变量),所以修改迭代变量的值对集合元素本身没有任何影响。

你的例子中,使用的是 String 类型作为元素,因为 String 属于自身不可变的特殊引用类型,所以改变元素的值不会影响集合本身中的元素。但如果用普通引用类型(如自己创建一个对象)作为元素,就会发现会影响集合本身中的元素。

public class Demo {

    public static void main(String args[]) {
        List<MyObject> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new MyObject(i));
        }

        System.out.println(list.toString());

        Iterator<MyObject> iterator = list.iterator();
        while (iterator.hasNext()) {
            MyObject next = iterator.next();
            next.num = 99;
        }

        System.out.println(list.toString());
    }
}
class MyObject {
    int num;

    MyObject(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return String.valueOf(num);
    }
}

输出结果:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[99, 99, 99, 99, 99, 99, 99, 99, 99, 99]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.