ARTS 第 55 周

题图:Photo by Emma Francis on Unsplash

每周完成一个 ARTS:
Algorithm: 每周至少做一个 LeetCode 的算法题
Review: 阅读并点评至少一篇英文技术文章
Tips: 学习至少一个技术技巧
Share: 分享一篇有观点和思考的技术文章

题图:Photo by Emma Francis on Unsplash

Contents

Algorithm

110. Balanced Binary Tree

题目:110. Balanced Binary Tree

难度:Easy

题意:Given a binary tree, determine if it is height-balanced.

For this problem, a height-balanced binary tree is defined as:

a binary tree in which the left and right subtrees of every node differ in height by no more than 1.

示例 1:

Given the following tree [3,9,20,null,null,15,7]:

    3
   / \
  9  20
    /  \
   15   7

Return true.

示例 2:

Given the following tree [1,2,2,3,3,null,null,4,4]:

       1
      / \
     2   2
    / \
   3   3
  / \
 4   4

Return false.

解法:

这道题也是典型的使用递归算法处理的题目,但是做起来有一个小 trick,我们先来看代码。

代码:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def get_height(root):
            if root is None:
                return 0
            left_height, right_height = get_height(root.left), get_height(root.right)
            if left_height < 0 or right_height < 0 or abs(left_height - right_height) > 1:
                return -1
            return max(left_height, right_height) + 1
        return (get_height(root) >= 0)

这道题的基本解决方法就是计算完左右两棵子树的高度之后做差,看差值是不是超过 1。在使用递归算法计算子树的高度时,我们注意到,如果子树中已经存在「左右两棵子树的高度差超过 1」的情况,那么其实就已经能判断出这棵树并不是一棵「平衡树」了。代码中第 13、14 行就是做这个判断的,并且返回值为 -1,意味着之后的所有递归返回值都是 -1。最后判断整体函数的返回值时,只需要判断递归函数的返回值是否大于等于 0 即可,归函数内部已经对树是否平衡做出了判断。

Review

How To Read Academic Content Once and Remember it Forever

本周阅读了来自 Medium 上《Better Humans》专栏的一篇文章《How To Read Academic Content Once and Remember it Forever》,作者是 iDoRecall.com 的联合创始人 David Handel 博士。他曾经是一个普通的高中学生(K-12 Student),但通过应用认知科学的学习技巧,最终以第一名的成绩从德雷塞尔大学医学院毕业。

在这篇文章中,David Handel 通过讲述自身的经验、讲解认知科学的研究成果,介绍并论证了如何仅读一遍学术资料就完全记住内容。这听起来有些玄学和鸡汤,让我们来看看他究竟是怎么做到的吧。

这篇文章很长,Medium 上标注了是 15 分钟读完,但我大概花了有 20 来分钟吧。但文中长难词并不多,而且文章的语言节奏很好,条理也很清晰,很容易读。

文章分了几大块,首先作者对「元认知」做了个大致的介绍,即「thinking about your thinking」。

接下来作者讲述了自己的经历,以及为什么他要把认知科学的技巧应用到自己身上。在这一节中,作者提出了这篇文章的任务,也即帮助你「consume the content once and remember it forever」。

在接下来的一节中,作者介绍了知识获取和知识留存。作者认为,知识获取的阶段是由元认知驱动的,而知识存留的阶段,则应该由不断地复习和回忆组成。在这一节中,作者也强调了基础知识的重要性。

接下来就是重头戏了,作者在这一节中讲述了如何在学习材料中找到并理解那些有用的知识。作者认为,「有技巧地选取有用的知识并嫁接到自己的知识库中」是个主动并且慎重的过程,而不应该使用像我们当中很多人会采用的「被动的多次阅读同一篇材料」的方法。这要求你能够对所阅读的部分进行理性的判断,哪些需要被撷取,哪些只是增添了颜色。你的任务是对阅读内容进行分析、理解和萃取。培养这种能力至关重要,也很难,有时候甚至如同军训一般。最好的情况下,你只需要读一遍而且之后再也不需要回头去读,但大多数情况下,你会在你的第一遍也是仅有的一遍阅读过程中,一遍一遍地重复阅读某个句子、某个段落或者某个小节。在这个过程中,你会应用你的元认知去一遍遍地解构和重构某个概念,你会需要对它构建一个心理的表征,可能是一个实物,也可能是一个虚构的概念或想法。而这个表征则会表示你如何理解、操纵和把玩这个概念。你会真正地消化这个概念并且将它和你已知的知识联系在一起。只有在这样一个过程中,你才会真正地去进行主动的阅读。在你对这些单词句子段落进行分析的时候,你需要对每个你想要记住的事实进行分析和评估,来确定自己是否真正地理解了它们。

作者表示,在阅读过程中,与其做些无效的笔记,他更倾向于使用一些更高效的工具,比如他会在阅读过程中制作一些 flashcards,以便自己在做回溯练习的时候遇到问题可以直接返回到相关的原文上去。这样可以方便地进行查漏补缺,并且快速地回到回溯练习中去。

「思考你正在阅读的材料——思考你是如何在脑中处理这些材料的」,这个过程实际上是心理环境的切换,当你在学习进行这种切换时,你会经历一个潜在的认知负荷,尤其是在元认知成为一种习惯之前。但这个过程会慢慢变得轻松,元认知是一个可以学会的东西。有时候碰到一些晦涩难懂的概念又没法看懂时,最好的方法是去寻找另一个解释这个概念的材料。与其纠结于一个作者的解释,你应该去看看其他专家是怎么说的。如果你没有浪费时间一遍又一遍的重读那些内容的话,你完全有空去读其他专家给出的解释。

之后作者还给出了一些在培养元认知中常用的问题,经常性地对自己提问可以帮助更快地形成自己的元认知。

最后一节,作者给出了如何把所学的东西牢牢记住的方法,这个方法就是「回溯练习」。所谓「回溯练习」,其实就是复习,但这种复习不是简单地重新去读,而是向自己提问,一旦遇到不会的,就返回去查看答案,再快速地回到练习中来。首先你要积极地去阅读和理解材料,然后通过制作 flashcards,记录下你要记住的关键概念和事实,最后用 flashcards 测试和培养你对所学知识的回忆能力。而对你最容易遗忘的那部分知识进行有针对性的回溯练习,则会让你事半功倍地记住这个概念(更容易地在将来回想起)。

在最后一节中作者还给出了一些关于「回溯练习为什么能如此有效地帮助人们记住知识」的科学依据,感兴趣的朋友可以点击文章链接查看。

Tips

在新电脑上构建与旧电脑相同的 Conda 环境

前段时间,我有一位朋友的电脑突然出了故障,于是被迫更换了硬盘重装了系统,用朋友自己的话讲:

我不是心痛要被洗劫一空的数据,毕竟数据可以备份。我是心痛我的 Python 环境要重新配置,以前辛辛苦苦装好的包们又要重装一次,那凝结了多少次的百度和 CSDN 的心血啊!

看到这里,我不禁嘴角上扬,伸出大拇指点了个赞,顺便留了个言:

Anaconda 支持构建完全相同的 Conda 环境的;另外上 Mac 吧「狗头」

这周我就来讲解一下如何在同一台或者不同的机器上配置同样的 Conda 环境吧(前提是同样的操作系统)!

首先,Conda 环境的同步是通过一个显式的文件来完成的,你可以使用命令行或者 Anaconda Prompt 执行以下命令来查看当前环境包含的包和依赖:

conda list --explicit

执行完这个命令之后你就能看到类似这样的说明:

# This file may be used to create an environment using:
# $ conda create --name <env> --file <this file>
# platform: osx-64
@EXPLICIT
https://repo.anaconda.com/pkgs/free/osx-64/mkl-11.3.3-0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/numpy-1.11.1-py35_0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/openssl-1.0.2h-1.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/pip-8.1.2-py35_0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/python-3.5.2-0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/readline-6.2-2.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/setuptools-25.1.6-py35_0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/sqlite-3.13.0-0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/tk-8.5.18-0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/wheel-0.29.0-py35_0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/xz-5.2.2-0.tar.bz2
https://repo.anaconda.com/pkgs/free/osx-64/zlib-1.2.8-3.tar.bz2

为了把这些说明放到一个文件中去,我们可以新建一个 txt 文件然后手动复制粘贴(当然我不建议这么做因为太蠢了 23333),或者可以使用 Linux 中的标准输出命令 > 直接将这些说明输出到一个文件中去,如下:

conda list --explicit > spec-file.txt

这里的 spec-file.txt 就是用来存储你的 Conda 环境的文件了,当然你可以给它改个名字比如 duoduo.txt 之类的。

需要注意的是,这里文件的第三行 # platform: osx-64 显示了运行当前 Conda 环境的系统,通常来说不建议在两个不同的系统下使用同一个 sepc-file.txt,因为有些包只存在于特定的系统(平台)上,或者一些依赖在新的系统里是缺失的。

在新的系统里(或者同一个系统下其实也行,就是需要给新的环境取个不一样的名字)构建新的一样的 Conda 环境,你需要在终端或者 Anaconda Prompt 里执行这样的命令:

conda create --name myenv --file spec-file.txt

那如果我已经有一个环境了,我想要安装之前的包和依赖怎么办呢?你可以使用:

conda install --name myenv --file spec-file.txt

其实就是把 create 换成 install 就可以了。

最后再强调一点,使用这种 spec-file 的形式来构建 Conda 环境,Conda 是不会为你检查各种库的依赖关系和操作系统的,所以你需要确保两个环境在同样的操作系统和 CPU 架构下,如 linux-64 或者 osx-64

所以如果大家害怕自己的环境丢失,就随手备份一下自己的环境咯~

更多细节请参考 Conda 的官方文档

Share

「技术隔离」十年后的独白

这周给大家分享的是一篇 ForkLog 上的文章,《After 10 Years in Tech Isolation, I’m Now Outsider to Things I Once Had Mastered》。文章作者是美国现代第一位以「损坏工业控制系统」的罪名被起诉的黑客,Jesse William McGraw, aka GhostExodus。

GhostExodus

作者在 2009 年被捕入狱,两年之后被强制隔离互联网,无法接触到外界的任何有关技术发展的消息。出狱之后,这位黑客看到了一个与自己的认知中完全不同的技术世界,比如 Windows 对于用户的控制更强、黑客正在成为科技巨头们热衷招募的员工、智能手机已经完全普及,等等。

在文章的最后一段,作者说:

For me, I stepped out into an uncertain future. I don’t really see meaningful human interaction anymore. I see a society that is impossibly distracted by likes and selfies, smartphones, and similar technologies, and I often find it frustrating to find my place in the midst of this new interconnected world simply because I was not there to naturally evolve with it. I was somewhere outside of time, on the other side of the looking glass. Waiting. Counting fractions of what felt like forever, for when I would be released back into society again. Only to discover a world I do not know.

翻译过来大意是:

「对我而言,我步入了一个不确定的未来。我再没有看过有意义的人际交往了。我看到的是一个被点赞、自拍、智能手机和类似的技术不可置信地分散了注意力的世界,我感觉在这个新的互联世界中找不到自己的位置,这很令人沮丧,而这仅仅只是因为我没有在这个世界中自然地和它一起进化。」

「(之前)我在时间之外的某个地方,在审讯室的另一边,等待着,数着永远也数不完的碎片,等着什么时候能再次被放回社会。而现在我回来了,却发现了一个我并不认识的世界。」

看完这篇文章,我歪楼似地想到了三个人。

第一个人是《无间道》中的傻强。在《无间道 2》中,傻强收到他父亲的死信后想出去送殡,狱警揍了他一顿告诉他:「知不知道什么叫坐牢?坐牢就是,就算你死老爸,也不能让你出去拜!你明不明啊?」

傻强

第二个人是《肖申克的救赎》中的老布。老布全名叫布鲁斯,在监狱图书馆里工作了 50 年,兢兢业业,却在获得假释后自杀。「监狱里的高墙实在是很有趣。刚入狱的时候,你痛恨周围的高墙;慢慢地,你习惯了生活在其中;最终你会发现自己不得不依靠它而生存。这就是体制化。」老布明白自己已经太老了,再也干不了那些犯罪的蠢事,但心中的恐惧让他整夜做噩梦,醒来不知身在何处。在绝望的谷底,他选择了上吊自杀,离开这个不喜欢的世界。

老布

第三个是快播的王欣。我不去判断王欣是否真的有罪,但很想知道他的内心。正值国内移动互联网蓬勃发展的几年,却进了局子,王欣出狱时的心情是否与文章作者类似呢?

王欣

最后,还是回归下文章真正想说的东西。这篇文章以一个奇怪的视角观察了当下充斥着人们生活的虚拟社会,却恰恰提出了一个几经讨论却也见仁见智的问题:当下这个被相对主义、虚无主义、消费主义和享乐主义所充斥的世界,真的能给我们提供良好的生活吗?

陈嘉映《何为良好生活》

WeChat QRCode