2020 年读书笔记

乌合之众:大众心理研究

群体不善于论证,却急于求成

创造并且引领文明的历来是为数不多的达官贵族,而不是群体。

你的生存本能正在杀死你:为什么你容易焦虑、不安、恐慌和被激怒?

人体是多么容易陷入恶性循环而难以自拔,以至于习惯性地按照某一种固定的方式做出重复的反应,仿佛循环播放同一段音乐的坏唱片一般。

编程之美

编程的乐趣在于探索,而不是在于背答案。面试的过程就是展现分析能力、探索能力的过程,在面试中展现出来的巧妙的思路、简明的算法、严谨的数学分析就是我们这本书要谈的“编程之美”

我的第一本算法书

数据存储于内存时,决定了数据顺序和位置关系的便是“数据结构”

我们只能访问最新添加的数据。

算法图解

log10100相当于问“将多少个10相乘的结果为100

数组和链表还被用来实现其他数据结构,

尾递归

如果两个键映射到了同一个位置,就在这个位置存储一个链表。

散列表使用数组来存储数据

!图由节点和边组成

动态规划先解决子问题,再逐步解决大问题。

远见(湛庐经典)

世界各地关注职业发展的人们正在他们的工作和私人生活之间寻求更大的灵活性和兼容性。

我们正在逐渐丧失热情。我们期盼梦想,但惧怕现实。

,虽然每个人身处的环境大相径庭,但他们的挑战核心并无差异。

“职场燃料”

当你遇到了新的路径和机会时,要保持冷静,有策略地思考。时刻准备好迎接无法避免的变化,并让自己的职业策略随机应变。

许多人关注的是职业生涯的表相:头衔、晋升、办公环境、薪水和奖励。这些可以算是职业生涯的重要里程碑

那些无法说服别人接受他们想法的人在职业生涯中都会受挫、贬值

,行业术语和高深辞藻并不能赢得听众,反而会失去他们

。说服力的一部分来自令人叹服的事实,它能让人们真正有理由相信你

,无论你拥有多高的智商或天赋,成功都需要花费超乎想象的时间进行高强度的练习

,获取关键的技能和经验必须花费一定的时间

。而人际关系的构建者会首先尝试帮助别人,他们不会有所保留。虽然他们心里清楚大部分好意都会得到回报,但是并不会精于算计。他们还会时刻维护自己的人际关系,而不是在需要的时候才想起来。

“当你有33%~66%的概率失败时,成长的速度也是最快的。要想精进,就得主动站在可能失败的立场上。

并承担越来越重的责任

这是一场战争。你正在竞争为数不多的职位,而竞争对手遍布全球,他们至少都跟你一样聪明、有魅力、有天赋。没人欠你一个职位。准备好被拒绝吧,而且可能会不止一次。

你会惊讶地发现,人们其实很愿意聊聊他们的工作

欢迎来到这个拒绝的世界。

。你不仅要为面试准备答案,还要花同样多的时间准备一些有水平的问题。

。如果你认真对待自己的职业生涯,那就需要了解更多的情况,搞清楚公司是怎么运转的:它怎么建立的,它的理念是什么,它如何赢利,它的关键人物有哪些,以及它的愿景如何

要想真正地出类拔萃,你就得成为一个能把故事讲好的人

任何高级管理人员都必须做到这一点,因为他是少数几个,甚至是唯一一个能看清全局的人

Go程序员面试算法宝典

《编程之美》《编程珠玑》《程序员面试笔试宝典

认真仔细地检查一些边界情况、异常情况及极性情况等,看是否也能满足要求。

,Hash往往可以缩小问题规模

。而用空间换时间最有效的方式就是Hash法、大数组和位图法

RPC是远程过程调用,其使用方式与调用一个普通函数一样,但执行体发生在远程机器上;

缓存、索引、数据分片及锁粒度尽可能小。

,头结点的数据域可以不存储任何信息

对单链表中任何一个结点的访问只能从链表的头指针开始进行遍历

(存储单元可以是不连续的)

有头结点的单链表和无头结点的单链表

链表首尾结点的特殊处理

永久记录

我这一代,是美国最后一代——或许也是世上最后一代——未数字化的世代,童年尚未上传到云端,大多局限在类比格式

网络应该启发人心,而不是追求赚钱

你通常清楚地知道自己制造出了什么样的内容,像是在电话里说了些什么,或是在邮件里写了什么。但你对自己制造出的元数据几乎没有任何掌控权,因为它是自动产生的。元数据是由机器收集、存储、分析与制造出来的,不需要经过你的参与以及核准。你的设备无时无刻不在为你沟通,不论你喜欢与否。人类依照自我意志进行沟通,但你的设备不一样,它们不会隐藏私人信息,也不会为了保密而使用密码。它们只知道将手机信号连上最近的基站。

私营企业不断利用我们对科技的依赖,巩固他们自家产品或服务的市场占有率。科技巨擘垄断了美国民众的网络生活,绝大多数人使用的是谷歌邮箱、脸书社交媒体与亚马逊电商平台,而美国情报机构充分利用这一点,除了直接下令要求这些公司交出登录系统权限,私底下更是从未停止过入侵的尝试。我们的个人资料为这些企业带来巨大的利益,但政府不花一毛钱就能窃取这些资料,这让我感到十分无力。

即使当时是2001年,公众还没注意到这个问题,但我已清楚看到科技的未来发展。

我架设了一部新的Tor服务器。没多久,全球各地的通信便经由我们家娱乐中心的笔记本电脑连上了网络,将我自己的网络活动隐藏在嘈杂声中。

有时候,我发现了一个可识别名称的程序,但又缺少一个对其用途的解释。有时候,我只是发现了一个不知名的解释,却看不出它描述的是一个执行中的项目,还是一个野心勃勃的计划。我不断地遇到文件隔间里有隔间,警告里套着警告,套件包含着套件,程序中又有程序。这就是国安局的本质——通过设计,左手几乎不知道右手在做什么。

最终结果是:你得到你想要的内容,连同你不想要的监视,而这一切发生在不到686毫秒的时间内。你完全不知情。

我挑选的文件全部加起来,正好存满一部驱动器,就放在我家里的办公桌上。我知道这些资料跟在办公室里一样安全。事实上,更加安全,因为层层加密,那正是加密技术的美妙之处。一丁点数学便可以保守秘密,这是枪支与带刺铁丝网所做不到的。

但事实上,我们以为的删除技术从来不曾存在过。删除不过是一种诡计、一种臆想、一种谎言,是一台计算机为了让你安心而跟你说的不高明的谎言。虽然删除的档案在你眼前不见了,却没有真正消失。就技术而言,删除其实只是一个过渡的形式,一种写入的形式。一般来说,当你删除一个档案,它的数据仍安然无恙,深埋在磁碟的某处。有效的现代作业系统,并不会单纯为了删除而设计用来在磁碟里深入搜寻的程式。相反,只有计算机的档案表,也就是记录每个档案储存所在的地图,被改写为:“我不再使用这个档案,且此档案已经失去重要性。”意思是说,原本应该消失的档案就像一座大型图书馆里被忽略的一本书,只要你努力找,还是可以找到。如果你只是消除书目,书本本身仍然存在。

简单来说,这是我在科学事实中所见过的最接近科幻小说的东西:你在这个界面可以输入近乎所有地址、电话号码或IP网址,然后搜索近期在线活动。在某些个案中,你甚至可以重现他们的在线对话记录,可以看到他们台式机屏幕的画面。你可以阅读他们的电子邮件、浏览记录、搜索记录、社交媒体帖文,以及所有的一切。你可以设定通知,每当你关注的人员或装置上线时就会发送通知。你可以搜索网络数据封包,看到关于某个人的搜索逐字跳出,因为许多网站在每个字母键入时便会传输出去。这就像看一份自动完成,字母与单字在屏幕上闪现。但是,输入动作的不是计算机而是人类:这是人工完成。

使用XKeyscore之后,你很快便会知道,几乎全世界每个上网的人都至少有两个共同点:他们都曾经看过色情内容,他们都储存了家人的照片和影片。

俄罗斯政府决定尽快摆平此事,还给莫斯科机场一个清净,不能总是被大批媒体包围。8月1日,俄罗斯决定给予我暂时庇护。莎拉和我得以离开谢列梅捷沃机场,她能回到美国老家。我们一起共患难的时光,让我和莎拉成为终生挚友。我永远感激,她这几周以来的陪伴,她是如此正直坦率、坚强勇敢。

当然,以上种种全部都已经发生了。

数据结构与算法图解

计算机程序总是在接收数据、操作数据或返回数据

数据结构则是指数据的组织形式

步数

种逐个格子去检查的做法,就是最基本的查找方法——线性查找

它是一种不允许元素重复的数据结构

集合就是一个带有“不允许重复”这种简单限制的数组

理解数据结构的性能,关键在于分析操作所需的步数

解决某个问题的一套流程

算法则是指某项操作的过程

有序数组相比常规数组的一大优势就是它除了可以用线性查找,还可以用二分查找

不过还要记住,有序数组并不是所有操作都比常规数组要快。如你所见,它的插入就相对要慢。衡量起来,虽然插入是慢了一些,但查找却快了许多。还是那句话,你得根据应用场景来判断哪种更合适。

影响算法性能的主要因素是其所需的步数。

O(1)

线性时间

常数时间

大O主要关注的是数据量变动时算法的性能变化

因为不管数据量怎样变化,算法的步数都恒定,所以这也是常数时间,也可以表示为O(1)

O(1)就是用来表示所有数据增长但步数不变的算法

对数时间

(log N)意味着该算法当数据量翻倍时,步数加1

对数

对数是指数的反函数

log28则将上述计算反过来,它意思是:要把2乘以自身多少次,才能得到8。因为需要3次

log28可以表达为:将8不断地除以2直到1,需要多少个2。

O(logN)算法的步数等于二分数据直至元素剩余1个的次数。

每次数据量翻倍时,O(N)算法的步数也跟着翻倍,O(log N)算法却只需加1。

如果你通过大O发现自己的算法比其他的要慢,你就应该退一步,好好想想怎样优化它,才能使它变成更快的那种大O。

将两个指针右移一格。

排序算法是计算机科学中被广泛研究的一个课题

每一次轮回过后,未排序的值中最大的那个都会“冒”到正确的位置上。

O(N2)算法是比较低效的,随着数据量变多,其步数也剧增,

二次时间

一旦看到嵌套循环,你就应该马上想到O(N2)。

从左至右检查数组的每个格子,找出值最小的那个

知道哪个格子的值最小之后,将该格与本次检查的起点交换

大O记法忽略常数。

非常强大的算法分析手法

散列表

散列表由一对对的数据组成。一对数据里,一个叫作键,另一个叫作值。

散列表就是一堆成对的元素

一种经典的做法就是分离链接。当冲突发生时,我们不是将值放到格子里,而是放到该格子所关联的数组里。

这就是使用散列表时所需要权衡的:既要避免冲突,又要节约空间。

栈和队列

事实上它们并不是全新的东西,只不过是多加了一些约束条件的数组而已。但正是这些约束条件为它们赋予了巧妙的用法。

栈和队列都是处理临时数据的灵活工具。在操作系统、打印任务、数据遍历等各种需要临时容器才能构造出美妙算法的场景,它们都大有作为。

❏ 只能在末尾插入数据。❏ 只能读取末尾的数据。❏ 只能移除末尾的数据。

栈很少用于需要长期保留数据的场景,却常用于各种处理临时数据的算法。

我们会类似地用栈去跟踪函数的调用,那也是递归的核心思想。

网络应用程序的函数调用,你应该都会需要栈来实现。

先进先出

队列也是处理异步请求的理想工具——它能保证请求按接收的顺序来执行

栈和队列是能巧妙解决各种现实问题的编程工具。

学习基于栈的递归。递归也是其他高级算法的基础

函数调用自身,就叫作递归

不再递归的情形称为基准情形

归是需要时间和练习才能适应的

计算机是用栈来记录每个调用中的函数。这个栈就叫作调用栈。

有趣的是,无限递归(如本章开头的例子)的程序会一直将同一方法加到调用栈上,直到计算机的内存空间不足,最终导致栈溢出的错误。

递归可以自然地用于实现那些需要重复自身的算法

递归十分适用于那些无法预估计算深度的问题

快速排序依赖于一个名为分区的概念

快速排序。

此处的分区指的是从数组随机选取一个值,以其为轴,将比它小的值放到它左边,比它大的值放到它右边

放置指针

假设有一个无序的数组,你不需要将它排序,只要找出里面第10小的值,或第5大的值。就像从一堆测试成绩中找出第25百分位,或找出中等成绩那样。你首先想到的,可能是把整个数组排序,然后再跳到对应的格子里去找。

其实能递归的不只有算法,还有数据结构。后面几章将要接触的链表、二叉树以及图,就利用了自身递归的特性,给我们提供了迅速的数据操作方式。

基于结点的数据结构拥有独特的存取方式,因此在某些时候具有性能上的优势。

与数组不同的是,组成链表的格子不是连续的。它们可以分布在内存的各个地方。这种不相邻的格子,就叫作结点。

链表相对于数组的一个好处就是,它可以将数据分散到内存各处,无须事先寻找连续的空格子。

data表示结点所保存的数据,next_node表示指向下一结点的链

LinkedList的作用就是一个指针,它指向链表的第一个结点。

读取链表的时间复杂度为O(N)。这跟读取数组的O(1)相比,的确是一大劣势。

链表的另一个引人注目的应用,就是作为队列的底层数据结构

你学会了在特定情况下使用链表来改善性能。后面还会介绍更复杂的基于结点的数据结构,它们更常用,并且对性能的提升更大。

既要保持顺序,又要快速查找、插入和删除,看来有序数组和散列表都不行。那还有什么数据结构可以选择?

一个普通的链表里,每一个结点会包含一个连接自身和另一结点的链。树也是基于结点的数据结构,但树里面的每个结点,可以含有多个链分别指向其他多个结点。

如果有两个子结点,则其中一个子结点的值必须小于父结点,另一个子结点的值必须大于父结点。

树形的数据结构除了二叉树以外还有很多种,包括堆、B树、红黑树、2-3-4树等。它们也各有自己适用的场景。

图是社交网络和地图软件等复杂应用的核心组成部分,强大且灵活。

图是一种善于处理关系型数据的数据结构,使用它可以很轻松地表示数据之间是如何关联的。

图的实现形式有很多,最简单的方法之一就是用散列表

有向图

无向图

图有两种经典的遍历方式:广度优先搜索和深度优先搜索。

我们关注的主要是代码运行的速度。我们以时间和算法的步数来衡量代码的性能。

答案当然是看情况。如果你想要程序跑得超级快,而且你的内存十分充足,那么用第二版会比较好。但如果你不看重速度,而且你的程序是跑在需要谨慎使用内存的嵌入式系统上,那你应该选择第一版。所有技术讨论都是这样的,当需要做出取舍时,你应从全局看待问题。

很多看似复杂、深奥的事物,其实都是由你所掌握的简单概念构筑而成的。不要因为某些资料没解释到位,就以为它很困难而被吓退,你一定能找到更详尽的解释资料。

程序员面试金典(第6版)

算法和数据结构

你必须学会开发新的算法,而不是死记硬背见过的题目

树、图、链表、排序等经常会在工作当中出现,所以应该掌握这些知识

白板编程

请注意编程风格。如果你从来没有经历过完整的代码审查流程,那么最好请有过相关经验的工程师帮忙审查一下代码。

你应该全面地讨论不同的解决方案和这些解决方案之间的取舍。

HackerRank.com

说说你碰到过的最棘手的bug

我该如何测试这段代码

否则,“温水煮青蛙”,拖得越久,你的目标就越难以实现。

吓人的题目

如果你打算问一个“吓人”的题目,那么一定要向求职者表明这并不需要专业知识。

紧张状态下的求职者会表现得很糟糕,但这并不意味着他们不优秀

求职者如何开发好算法的内容

通过实施分布式缓存功能减少了75% 的对象渲染时间,从而使得用户登录速度加快了10%。”

但原则无非是描述做过什么,如何完成,结果如何。理想的做法是尽可能地量化结果。

将搜索操作的时间复杂度由O(n)降至O(logn)

表示时间的大O符号,是用来描述算法效率的语言和度量单位。不彻底理解这个概念,开发算法就格外艰难。它不仅会影响你做出清晰的判断,还会让你无法评价算法的优劣。请务必掌握这个概念。

最优情况

最坏情况

期望情况

时间并不是算法唯一要关心的东西,还得关心内存数量或空间大小。

在递归中,栈空间也要算在内

如果你的算法是“做这个,结束之后做那个”的形式,就是加;❑ 如果你的算法是“对这个的每个元素做那个”的形式,就是乘。

二分查找为例

平衡二叉搜索树

解题时还要考虑空间和时间效率

就是要在纸上写下一般用例、基本用例和错误用例等。面试中就得这么做,因此最好提前做好准备。

你一旦有了蛮力法,就应该努力优化该方法

使用散列表。散列表在面试题中用途广泛,你应该第一个想到它。

这是你靠大脑做出的一个优化,在设计算法时也应该留意到

我们可以简单过一遍所有的数据结构

理解了大O时间

如果你曾见过某个面试题,要提前说明。面试官问你这些问题是为了评估你解决问题的能力。如果你已经知道某个题的答案了,他们就无法准确无误地评估你的水平了。

请注意,数组问题与字符串问题往往是相通的。换句话说,书中提到的数组问题也可能以字符串的形式出现,反之亦然。

我们使用一个链表构成的数组与一个散列函数来实现散列表

平衡二叉搜索树

在处理链表问题时,“快行指针”(或称第二个指针)是一种很常见的技巧。“快行指针”指的是同时用两个指针来迭代访问链表,只不过其中一个比另一个超前一些。“快”指针往往先行几步,或与“慢”指针相差固定的步数。

许多链表问题都要用到递归

树是由节点构成的数据结构

二叉树是指每个节点至多只有两个子节点的树。并不是所有的树都是二叉树。例如,下图所示就不是一棵二叉树,你可称其为三叉树。

对实现中序、后序和前序遍历,你要做到轻车熟路,其中在面试中最常见的是中序遍历。

树实际上是图的一种,但并不是所有的图都是树。简单地说,树是没有环路的连通图。

图是节点与节点之间边的集合。

两种常见的图搜索算法分别是深度优先搜索(depth-first search,DFS)和广度优先搜索(breadth-first search,BFS)。

计算机通常以二进制补码的表示形式存储整数

问题属不属于递归问题,就看它是否能分解为子问题。

递归算法极其耗空间。每次递归调用都会增加一层新的方法入栈,简而言之,如果递归深度为n,那么最少占用O(n)的空间。

人们对于动态规划问题的恐惧有些小题大做了

动态规划就是使用递归算法发现重叠子问题(也就是重复的调用)。然后你可以缓存结果以备不时之需。

慢操作最好用异步处理

切勿假设使用者会做到运用自如,而是做好应对用户误用乱用软件的准备。

人工智能的未来:自主智能体与AI安全终极挑战

这也意味着我们的记忆是连贯有序的,可以按照记忆刻入时的顺序获取,却无法倒序获取。

你要在头脑中重建图像,因为真实的图像并不存在。

事实证明,放宽职业禁忌对创造性地解决问题非常有效

人工智能领域并不是尝试复制人脑,却仍然达到可与人脑匹敌的技术水准。

抛弃大多数输入信息,仅保留最显著的细节

Go语言开发实战(慕课版)

Go语言不使用虚拟机,Go语言的代码可以直接输出为目标平台的二进制可执行文件

Go语言的使用者只需要关注内存的申请而不必关心内存的释放,Go语言内置runtime来自动进行管理

GOPATH主要包含三个目录:bin、pkg、src。bin目录主要存放可执行文件;pkg目录主要存放编译好的库文件,如*.a文件;src目录主要存放Go的源文件。

package main表示一个可独立执行的程序,每个Go应用程序都需要包含一个名为main的包,并且该包包含一个叫main()的函数(该函数是Go可执行程序的执行起点,既不能带参数,也不能定义返回值)。

所有Go函数以关键字func开头

每一个可执行程序都必须包含main()函数,通常是程序启动后第一个执行的函数,如果有init()函数则会先执行init()函数。

自定义标识符实际上是一个或多个字母(A~Z和a~z)、数字(0~9)、下画线(_)组成的序列,但是第一个字符必须是字母或下画线,而不能是数字。

Go是一种区分大小写的编程语言。因此,Manpower和manpower是两个不同的标识符。

在Go程序中,换行代表一个语句结束。Go语言中不需要像Java一样以分号结尾,因为这些工作都将由Go编译器自动完成。

Go语言中,使用大小写来决定标识符(常量、变量、类型、接口、结构或函数)是否可以被外部包所调用。如果标识符以一个大写字母开头,那么其对象就可以被外部包的代码所使用(使用时程序需要先导入这个包),如同面向对象语言中的public。如果标识符以小写字母开头,则对包外是不可见的,但是它们在整个包的内部是可见并且可用的,如同面向对象语言中的private。

十善业道:洗心禅2

我们所遇到的一切困扰,都是源于内心的不慈悲

为了你的家庭和事业,你要勇敢地去面对一切,纠正一切。

让自己打破原有的惯性思维吧,只有打破,才会诞生新的理念。我们要不断地从自我的狭隘里面超脱出来,只有打破原有的框架束缚,才能大彻大悟。

Go语言高级编程

设计网络和多核时代的C语言

并发特性

最终Go语言演化出了自己特有的支持鸭子面向对象模型的隐式接口等诸多特性

顺序通信进程

Go程序都由最基本的函数和变量构成

Go语言闭包函数对外部变量是以引用的方式使用的

Go语言开始采用是否大小写首字母来区分符号是否可以导出。大写字母开头表示导出的公共符号,小写字母开头表示包内部的私有符号

Go语言终于移除了语句末尾的分号

Redis 5设计与源码分析

C语言和网络编程等基础理论知识

娱乐至死

在他看来,人们会渐渐爱上压迫,崇拜那些使他们丧失思考能力的工业技术。

奥威尔害怕的是那些剥夺我们信息的人,赫胥黎担心的是人们在汪洋如海的信息中日益变得被动和自私;奥威尔害怕的是真理被隐瞒,赫胥黎担心的是真理被淹没在无聊烦琐的世事中;奥威尔害怕的是我们的文化成为受制文化,赫胥黎担心的是我们的文化成为充满感官刺激、欲望和无规则游戏的庸俗文化。

政治家原本可以表现才干和驾驭能力的领域已经从智慧变成了化妆术。

如果没有用来宣传它们的技术,人们就无法了解,无法把这一切纳入自己的日常生活。简而言之,这些信息就不能作为文化的内容而存在

墨菲定律:每天学点心理学

如果事情有变坏的可能,不管这种可能性有多小,它总会发生。