# Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

## 聊聊那些加塞狗

发表于 2021-01-17 分类于 生活 ， 开车 阅读次数： Disqus：

今天真的是被气得不轻，情况是碰到一个有 70 多秒的直行红灯，然后直行就排了很长的队，但是左转车道没车，就有好几辆车占着左转车道，准备往直行车道插队加塞，一般这种加塞的，会挑个不太计较的，如果前面一辆不让的话就再等等，我因为赶着回家，就不想让，结果那辆车几次车头直接往里冲，当时怒气值基本已经蓄满了，我真的是分毫都不想让，如果路上都是让着这种人的，那么这种情况只会越来越严重，我理解的这种心态，就赌你怕麻烦，多一事不如少一事，结果就是每次都能顺利插队加塞，其实延伸到我们社会中的种种实质性的排队或者等同于排队的情况，都已经有这种惯有思维，一方面这种不符合规则，可能在严重程度上容易被很多人所忽视，基本上已经被很多人当成是“合理”行为，另一方面，对于这些“微小”的违规行为，本身管理层面也基本没有想要管的意思，就更多的成为了纵容这些行为的导火索，并且大多数人都是想着如果不让，发生点小剐小蹭的要浪费很多时间精力来处理，甚至会觉得会被别人觉得自己太小气等等，诸多内外成本结合起来，会真的去硬刚的可能少之又少了，这样也就让更多的人觉得这种行为是被默许的，再举个非常小的例子，以我们公司疫情期间的盒饭发放为例，有两个比较“有意思”的事情，第一个就是因为疫情，本来是让排队要间隔一米，但是可能除了我比较怕死会跟前面的人保持点距离基本没别人会不挨着前面的人，甚至我跟我前面的人保持点距离，后面的同学会推着我让我上去；第二个是关于拿饭，这么多人排着队拿饭，然后有部分同学，一个人拿好几份，帮组里其他人的都拿了，有些甚至一个人拿十份，假如这个盒饭发放是说明了可以按部门直接全领了那就没啥问题，但是当时的状况是个人排队领自己的那一份，如果一个同学直接帮着组里十几个人都拿了，后面排队的人是什么感受呢，甚至有些是看到队伍排长了，就找队伍里自己认识的比较靠前的人说你帮我也拿一份，其实作为我这个比较按规矩办事的“愣头青”来说，我是比较不能接受这两件小事里的行为的，再往下说可能就有点偏激了，先说到这~

## Leetcode 160 相交链表(intersection-of-two-linked-lists) 题解分析

发表于 2021-01-10 分类于 Java ， leetcode ， Linked List ， java ， Linked List 阅读次数： Disqus：

## 题目介绍

写一个程序找出两个单向链表的交叉起始点，可能是我英语不好，图里画的其实还有一点是交叉以后所有节点都是相同的
Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:
begin to intersect at node c1.

### Example 1:

    Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
    Output: Reference of the node with value = 8
    Input Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.

## 分析题解

一开始没什么头绪，感觉只能最原始的遍历，后来看了一些文章，发现比较简单的方式就是先找两个链表的长度差，因为从相交点开始肯定是长度一致的，这是个很好的解题突破口，找到长度差以后就是先跳过长链表的较长部分，然后开始同步遍历比较 A，B 链表；

### 代码

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            if (headA == null || headB == null) {
                return null;
            }
            // 算 A 的长度
            int countA = 0;
            ListNode tailA = headA;
            while (tailA != null) {
                tailA = tailA.next;
                countA++;
            }
            // 算 B 的长度
            int countB = 0;
            ListNode tailB = headB;
            while (tailB != null) {
                tailB = tailB.next;
                countB++;
            }
            tailA = headA;
            tailB = headB;
            // 依据长度差，先让长的链表 tail 指针往后移
            if (countA > countB) {
                while (countA > countB) {
                    tailA = tailA.next;
                    countA--;
                }
            } else if (countA < countB) {
                while (countA < countB) {
                    tailB = tailB.next;
                    countB--;
                }
            }
            // 然后以相同速度遍历两个链表比较
            while (tailA != null) {
                if (tailA == tailB) {
                    return tailA;
                } else {
                    tailA = tailA.next;
                    tailB = tailB.next;
                }
            }
            return null;
        }

### 总结

可能缺少这种思维，做的还是比较少，所以没法一下子反应过来，需要锻炼，我的第一反应是两重遍历，不过那样复杂度就高了，这里应该是只有 O(N) 的复杂度。

## 聊聊 Java 的 equals 和 hashCode 方法

发表于 2021-01-03 阅读次数： Disqus：

Java 中的这个话题也是比较常遇到的，关于这块原先也是比较忽略的，但是仔细想想又有点遗忘了就在这里记一下
简单看下代码
`java.lang.Object#equals`

    public boolean equals(Object obj) {
            return (this == obj);
        }

对于所有对象的父类，`equals` 方法其实对比的就是对象的地址，也就是是否是同一个对象，试想如果像 Integer 或者 String 这种，我们没有重写 `equals`，那其实就等于是在用`==`，可能就没法达到我们的目的，所以像 String 这种常用的 jdk 类都是默认重写了
`java.lang.String#equals`

    public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }

然后呢就是为啥一些书或者 `effective java` 中写了 `equals` 跟 `hashCode` 要一起重写，这里涉及到当对象作为 `HashMap` 的 `key` 的时候
首先 `HashMap` 会使用 `hashCode` 去判断是否在同一个槽里，然后在通过 `equals` 去判断是否是同一个 `key`，是的话就替换，不是的话就链表接下去，如果不重写 `hashCode` 的话，默认的 `object` 的`hashCode` 是 `native` 方法，根据对象的地址生成的，这样其实对象的值相同的话，因为地址不同，`HashMap` 也会出现异常，所以需要重写，同时也需要重写 `equals` 方法，才能确认是同一个 `key`，而不是落在同一个槽的不同 `key`.

## 聊聊 mysql 索引的一些细节

发表于 2020-12-27 分类于 Mysql ， C ， 索引 ， Mysql 阅读次数： Disqus：

前几天同事问了我个 mysql 索引的问题，虽然大概知道，但是还是想来实践下，就是 is null，is not null 这类查询是否能用索引，可能之前有些网上的文章说都是不能用索引，但是其实不是，我们来看个小试验

    CREATE TABLE `null_index_t` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `null_key` varchar(255) DEFAULT NULL,
      `null_key1` varchar(255) DEFAULT NULL,
      `null_key2` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_1` (`null_key`) USING BTREE,
      KEY `idx_2` (`null_key1`) USING BTREE,
      KEY `idx_3` (`null_key2`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

用个存储过程来插入数据

    delimiter $	#以delimiter来标记用$表示存储过程结束
    create procedure nullIndex1()
    begin
    declare i int;
    declare j int;
    set i=1;
    set j=1;
    while(i<=100) do
    	while(j<=100) do
    		IF (i % 3 = 0) THEN
    	     INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (null , LEFT(MD5(RAND()), 8), LEFT(MD5(RAND()), 8));
        ELSEIF (i % 3 = 1) THEN
    			 INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (LEFT(MD5(RAND()), 8), NULL, LEFT(MD5(RAND()), 8));
    	  ELSE
    			 INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (LEFT(MD5(RAND()), 8), LEFT(MD5(RAND()), 8), NULL);
        END IF;
    		set j=j+1;
    	end while;
    	set i=i+1;
    	set j=1;
    end while;
    end
    $
    call nullIndex1();

然后看下我们的 is null 查询

    EXPLAIN select * from null_index_t WHERE null_key is null;

再来看看另一个

    EXPLAIN select * from null_index_t WHERE null_key is not null;

从这里能看出来啥呢，可以思考下

从上面可以发现，`is null`应该是用上了索引了，所以至少不是一刀切不能用，但是看着`is not null`好像不太行额
我们在做一点小改动，把这个表里的数据改成 9100 条是 null，剩下 900 条是有值的，然后再执行下
然后再来看看执行结果

    EXPLAIN select * from null_index_t WHERE null_key is null;

    EXPLAIN select * from null_index_t WHERE null_key is not null;

是不是不一样了，这里再补充下我试验使用的 mysql 是 5.7 的，不保证在其他版本的一致性，
其实可以看出随着数据量的变化，mysql 会不会使用索引是会变化的，不是说 is not null 一定会使用，也不是一定不会使用，而是优化器会根据查询成本做个预判，这个预判尽可能会减小查询成本，主要包括回表啥的，但是也不一定完全准确。

## 从丁仲礼被美国制裁聊点啥

发表于 2020-12-20 分类于 生活 ， 吐槽 ， 疫情 ， 美国 阅读次数： Disqus：

几年前看了柴静的《穹顶之下》觉得这个记者调查得很深入，挺有水平，然后再看到了她跟丁仲礼的采访，其实没看完整，也没试着去理解，就觉得环境问题挺严重的，为啥柴静这个对面的这位好像对这个很不屑的样子，最近因为丁仲礼上了美国制裁名单，B 站又有人把这个视频发了出来，就完整看了下，就觉得自己挺惭愧的，就抱着对柴静的好感而没来由的否定了丁老的看法和说法，所以人也需要不断地学习，改正之前错误的观点，当然不是说我现在说的就是百分百正确，只是个人的一些浅显的见解

先聊聊这个事情，整体看下来我的一些理解，IPCC给中国的方案其实是个很大的陷阱，它里面有几个隐藏的点是容易被我们外行忽略的，第一点是基数，首先发达国家目前（指2010年采访或者IPCC方案时间）的人均碳排放量已经是远高于发展中国家的了，这也就导致了所谓的发达国家承诺减排80%是个非常有诚意的承诺其实就是忽悠；第二点是碳排放是个累计过程，从1900年开始到2050年，或者说到2010年，发达国家已经排的量是远超过发展中国家的，这是非常不公平的；第三点其实是通过前两点推导出来的，也就是即使发达国家这么有诚意地说减排80%，扒开这层虚伪的外衣，其实是给他们11亿人分走了48%的碳排放量，留给发展中国家55亿人口的只剩下了52%；第四点，人是否因为国家的发达与否而应受到不平等待遇，如果按国家维度，丁老说的，摩纳哥要跟中国分同样的排放量么，中国人还算不算人；第五点，这点算是我自己想的，也可能是柴静屁股决定脑袋想不到的点，她作为一个物质生活条件已经足够好了，那么对于那些生活在物质条件平均线以下的，他们是否能像城里人那样有空调地暖，洗澡有热水器浴霸，上下班能开车，这些其实都直接或者间接地导致了碳排放；他们有没有改善物质生活条件地权利呢，并且再说回来，其实丁老也给了我们觉得合理地方案，我们保证不管发达国家不管减排多少，我们都不会超过他们的80%，我觉得这是真正的诚意，而不是接着减排80%的噱头来忽悠人，也是像丁老这样的专家才能看破这个陷阱，碳排放权其实就是发展权，就是人权，中国人就不是人了么，或者说站在贫困线以下的人民是否有改善物质条件的权利，而不是说像柴静这样，只是管她自己，可能觉得小孩因为空气污染导致身体不好，所以做了穹顶之下这个纪录片，想去改善这个事情，空气污染不是说对的，只是每个国家都有这个过程，如果不发展，哪里有资源去让人活得好，活得好了是前提，然后再去各方面都改善。

对于这个问题其实更想说的是人的认知偏差，之前总觉得美帝是更自由民主，公平啥的，或者说觉得美帝啥都好，有种无脑愤青的感觉，外国的月亮比较圆，但是经历了像川普当选美国总统以来的各种魔幻操作，还有对于疫情的种种不可思议的美国民众的反应，其实更让人明白第一是外国的月亮没比较圆，第二是事情总是没那么简单粗暴非黑即白，美国不像原先设想地那么领先优秀，但是的确有很多方面是全球领先的，天朝也有体制所带来的优势，不可妄自菲薄，也不能忙不自大，还是要多学习知识，提升认知水平。