第 4 周 ARTS

一、Algorithms

100. Same Tree

本周做的还是 DFS 相关的问题,题目要求是比较两棵二叉树是否相同,即每个节点相同并且 val 相等

思路

开始的思路是使用深度遍历访问到两棵树的每个节点并比较 val 是否相同,如果一直到遍历结束都相同那么说明是同一棵树。但这样的问题是每次都需要遍历所有节点,正确的做法应该是一旦发现不同立即返回即可。

先假设两个树是相同的。然后同时开始对两棵树进行 DFS,一旦有一个节点其类型不一致或者 val 不一致,就表示两棵树不相同,此时终止遍历返回即可。这样好处时当两棵树不一致时可以将遍历次数降到最低,在两棵树相同时遍历次数最多,运行时间最长。

实现代码如下, 运行时间 3ms, beats 99.91%。

class Solution {

    private boolean isSame = true;

    public boolean isSameTree(TreeNode p, TreeNode q) {

        if (p == null && q == null) {
            return true;
        } else if (p instanceof TreeNode && q instanceof TreeNode) {
            if (p.val != q.val) {
                return false;
            }

        } else {
            return false;
        }

        dfs(p, q);

        return isSame;

    }

    public void dfs(TreeNode p, TreeNode q) {

        if (p == null && q == null){
            return;
        }
        if ((p instanceof TreeNode) && (q instanceof TreeNode)) {
            if (p.val != q.val) {
                isSame = false;
                return;
            }

        }else {
            isSame = false;
            return ;
        }
        dfs(p.left, q.left);
        dfs(p.right, q.right);
    }

}

二. Review

最近公司在上 ES,因此本周读了耗子哥在专栏中推荐的一篇文章 9 tips on ElasticSearch configuration for high performance

文中主要提到了几点优化建议:

  • master 节点维护集群状态,包括索引 mapping、分配分片,追踪每个 Index 和 shard 的状态,这些数据的维护都需要消耗资源。因此如果允许 Index 无限制的增加,那么最终会导致集群状态数据过多导致 master 节点挂掉。
  • 在线上部署时尽量使 client、data 和 master 节点分离。
  • 设置bootstrap.memory_lock: true, 可提升读写效率
  • 关闭批量删除功能,这是一个高危操作: action.destructive_requires_name true
  • 当需要用到过滤和聚合分析功能时建议开启 field 的 doc_values 属性
  • ES 通过 discovery.zen 来设置与其他节点通信的相关配置,主要有以下三个
# 集群中其他节点的 host,主要是 master-elgible node
discovery.zen.ping.unicast.hosts: ["esmaster01","esmaster02","esmaster03"]
# ES ping 节点的超时时间
discovery.zen.fd.ping_timeout: 30s
# 最小选举数
discovery.zen.minimum_master_nodes: 2

minimum_master_nodes 设置的是最小选举数。即当集群出现网络问题某一个 master 节点失效后,只有当集群的 master-eligible 节点大于等于 minimum_master_nodes 时 时才可以进行 master 节点的选举,这主要是为了避免脑裂问题.

也可以通过如下 api 进行设置。

PUT _cluster/settings
{
   # transient 配置不是持久性的,集群重启后就失效
   # persistent 可以进行持久化的修改
  "transient": {
    "discovery.zen.minimum_master_nodes": 2
  }
}

另外还有三个 tip 其相关内容还没有完全搞明白,下周搞清楚与下周的 review 一起发。

三、Technique

分享一个 Linux 的命令行使用吧,我们经常使用 htop 查看系统运行情况,或者使用 ps 查看某个进程的运行,在使用 ps 时可以结合 sort 命令 对查询出的进程按照内存占用率和 CPU 占用率进行排序, 通过这个命令也可以快速的查看哪些程序占用了过多的资源:

# 按照 cpu 利用率排序
ps aux | sort -nk 3
# 按照内存使用率进行排序
ps aux | sort -nk 4

这里也顺便分享一个查询 Linxu 命令用法的网站 linux-command, 对于 man 命令读英文不太习惯的同学可以用这个网站快速查询用法。

四. share

本周读了耗子哥专栏编程范式系列中关于泛型的文章,对应的也读了 《冒号课堂》一书关于泛型的介绍,两份资料都表达的相似的观点:

  • 泛型,本质上是使算法脱离于具体的数据结构,使其具有更加的通用性。

在实际的操作中,开始工作的时候用的是 Java,现在用 Python。个人体验上动态语言在编写程序时确实提高了程序的通用性,专注于要实现的逻辑即可,不必考虑各种数据类型。但随之而来的就是可读性的下降。当回头去看很久之前的一段代码时,除非命名的特别合理清晰,否则经常要花费一定的时去梳理逻辑,搞清楚某个变量的类型和意义是什么,尤其是自定义的对象类型。而 Java 虽然也有泛型,但是还是一门静态语言,个人感觉代码整体的可读性和可维护性都要比 Python 好,因为类型的存在可以很直观的知晓我们的程序是处理哪种数据的。泛型也算是一种 trade-off 吧,在牺牲可读性的基础上提高了通用性,使我们的代码更加符合 DRY 原则,同时不必因为类型而重复多份,也一定程度的提高了开发效率。

发布了46 篇原创文章 · 获赞 21 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Ahri_J/article/details/105396887