ARTS是什么?
Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章。
Algorithm
题目解析:
给你一个图,让你完整地拷贝一份。这道题目不难,但是在实际的工作项目中却时常遇到。这道题目有很多种解法,但是建议站在实际工作的角度去思考。
图是由一个个节点组成的,完整地拷贝一份图,那么就意味着我们要对每个节点进行拷贝,而且节点与节点的关系也要拷贝过来。做到这一点也不难,我们只需要遍历一遍图就可以了,这里的关键点在于题目强调是 无向图,也就是说我们可以从图上的任意点出发到达图上的所有节点。那么问题从而就转换到了如何遍历图,我们可以使用广度优先搜索,也可以使用深度优先搜索,从工作的角度出发,比较推荐广度优先搜索,因为理解容易,实现简单,而且不涉及栈溢出的问题,处理大规模数据比较安全。
一般使用广度优先搜索遍历图,时间复杂度是 O(n + m),其中这里的 n 表示的是图上的节点数,m 表示的图上的边的数量。从广度优先搜索的 由点及面 的性质,你不难理解这个结果。极端情况下,当这张图是一张全联通的图,时间复杂度就会是 O(n^2),解释起来也很容易,因为你每访问完一个节点,下面都会去访问相邻的节点,一个节点和所有的节点相连,那么在一个节点上花费的时间就是 n,在 n 节点上花费的时间就是 n^2。因为我们使用了队列存放接下来需要遍历的节点,空间复杂度就是 O(n)。
参考代码:
public Node cloneGraph(Node node) {
if (node == null) {
return null;
}
Map<Node, Node> map2NewNode = new HashMap<>();
// 利用广度优先搜索遍历图,并复制每一个节点
// 用一个 Map 存放 旧节点-新节点 的对应关系
bfsTraverse(node, map2NewNode);
// 复制节点之间的关系,也就是复制图上的边
// 这里将复制节点和复制边分开进行会比较清晰直观
// 你也可以选择直接在广度优先搜索的时候完成,时间复杂度方面没有区别
for (Map.Entry<Node, Node> entry : map2NewNode.entrySet()) {
Node cur = entry.getKey();
Node newNode = entry.getValue();
for (Node nei : cur.neighbors) {
Node newNei = map2NewNode.get(nei);
newNode.neighbors.add(newNei);
}
}
return map2NewNode.get(node);
}
private void bfsTraverse(Node node, Map<Node, Node> map2NewNode) {
Queue<Node> queue = new LinkedList<>();
queue.offer(node);
map2NewNode.put(node, new Node(node.val, new ArrayList<Node>()));
while (!queue.isEmpty()) {
Node cur = queue.poll();
for (Node nei : cur.neighbors) {
if (!map2NewNode.containsKey(nei)) {
queue.offer(nei);
map2NewNode.put(nei, new Node(nei.val, new ArrayList<Node>()));
}
}
}
}
Review
Decide Where You Want To Be In 10 Years And Get There In 6 Months
非常好的一篇短文,它主要强调的是一个 学习的误区。出生在应试教育下的我们,往往被告知要努力做题,拼命复习才有所谓的 “未来”。但是一上到社会,我们发现自己掌握的实用技能真的很少,要学的东西真的很多。这个时候我们还会被工作上面的老前辈告知,自己需要多少多少年的刻苦努力,和敢于反复试错的精神,才能有他们现在的经验和能力。事情真的是这样吗?我们只需要努力就够了吗?时间会告诉我们答案?
你不知道你不知道的东西。你再怎么努力尝试,拼命加班也无法获得新的知识。有些东西尝试 10 遍和尝试 100 遍没有太大的差别。就比方说你 for 循环写得再熟练,如果你不去阅读,去看别人的分享,你也无法知道有动态规划这个东西。没有输入,哪来的输出?在遇到瓶颈的时候,或是初入某个领域,初学某项技术的时候,我们需要做的不是借鉴自己之前的经验,反复试错,反复尝试,这样确实可以让自己学得更扎实,但是这样做会平白无故耗费大量的时间。更加正确的做法是去阅读牛人写的书或者是分享,这会让自己少走很多弯路,有些坑我们没必要去尝试,因为已经有前车之鉴可以拿来参考了。所以,当自己对某项技术或者是说在某个领域碰壁的时候,千万不要使蛮力,你应该做的是多多请教周围有经验的人,还有就是多读相关书籍,多多去接触新的东西,很多时候,好奇心比努力更重要。
Tip
有一个关于 Linux 的命令的 查询网站,你直接在网站上输入具体的命令关键字,就可以获得命令的用法和例子,对于熟悉 Linux 一些功能强大的命令非常有帮助,这次来学习并记录一下 grep 这个命令:
-
grep <要找的字符串> <文件路径>
这个命令会输出包含要找的字符串的行内容
-
grep -i <要找的字符串> <文件路径>
和上面一样,但是这里加上 -i 表示不区分大小写
-
grep -RI <要找的字符串> <路径>
可以在某个目录下递归搜索要找的字符串,很上面一样,也是输出内容行
-
grep -E <正则表达式> <路径>
使用正则进行匹配搜索
-
grep -<C|B|A> 3 <要找的字符串> <文件路径>
-C 表示打印出要找的字符串的上下 3 行
-B 表示打印出要找的字符串的上面 3 行
-A 表示打印出要找的字符串的下面 3 行 -
grep -Hn <要找的字符串> <文件路径>
-Hn 表示打印出文件名和行数,(-H 表示打印出文件名,-n 表示打印出具体行数)
-
cat {{path/to/file}} | grep {{search_string}}
和
grep <要找的字符串> <文件路径>作用一样 -
grep -v <要找的字符串> <文件路径>
打印不包含要找的字符串的行内容
Share
今天分享一篇 Medium 上的文章
Here’s Why You Give Up on Most of Your Goals After Two Weeks
之所以分享出来,是因为这篇文章说出了大多数人的困惑。很多时候我们总会抱怨自己做事情不能够坚持,干什么都是三分钟的热度。这里的原因具体是什么呢?我们如何才能让自己朝着目标坚定的走下去呢?
文章中说,我们一般都会经历下面一个过程
- 和别人对比,发现自己身上的某些特质不符合自己的期待(比如身材不够好,技术不够牛,知识面不广等等),这会让你感到不舒服,总感觉需要做些什么
- 定下计划,发下毒誓,脑袋里面幻想着一个目标(通常是拿别人做参照)
- 执行计划的头几天你会感觉自己在离目标越来越近
- 执行一段时间后,你发现自己和别人的差距其实也没有那么大,成功的秘密对你来说已经不再是秘密,你完全可以实现目标,只是时间问题,这让你自己心里好受许多。但是这个时候,其他的事情引起了你的关注,这些事情和当前你坚持的事情有冲突,比如说你发现人要学会善待自己,或者看了身边人的经历,觉得技术好并不是绝对能让自己飞黄腾达,于是你的内心开始摇摆
- 你选择了放弃,选择不去坚持
- 直到某一天,你又发现自己之前存在并尝试解决的问题让自己又不爽了,于是又开始循环上面的过程...
我们为什么会这样?这里存在的第一个问题在于 我们并不清楚我们具体想要的是什么,你减肥想要得到的是别人的夸奖和赞美,还是想要的是一个好的身体。你努力学习新技术想要的是升官发财走向人生巅峰,还是想让自己的生命中有更多的可能。做事情如果没有一个很具体的目的和目标,在坚持的过程中就会很容易迷失自己,很容易被外界的变化所影响,因为你会觉得自己好像已经不像当初那么难受了,自己已经达到了自己之前想要的状态了。很多时候,看似想要的东西其实根本不是自己真正想要的,你需要反复跟自己确认。
第二个问题在于 我们并不清楚该如何去得到我们想要的,很多时候我们做一些事情并不能马上看到结果,会很对自己的做法和决心产生各种疑问。这种时候该做的应该是针对具体的事情力所能及地去制定解决方案,而不是对自己或者自己的能力产生疑问,只有当你学会沉浸到做事情本身的乐趣之中,暂时忘掉自己那些宏伟的梦想,才能走的更远。