Arts 第七十一周(8/24 ~8/30)

130 阅读10分钟

ARTS是什么?
Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章。

Algorithm

LC 143. Reorder List

题目解析

题目给的信息量不多,输入一个链表,然后让你按一定的规则变换链表节点的位置。变换信息如下:

L0→L1→…→Ln-1→Ln
	变换为
L0→Ln→L1→Ln-1→L2→Ln-2→…

并且题目要求不能改变节点的值。

这道题目属于链表题目中较为复杂的一类,考察了常见的链表操作。很能锻炼编程的基本功。拿到题目,我们首先需要思考的是,我们该如何变换成第二种格式?对比发现,链表的前半部分好像和后半部分交叉在一起了,但是貌似后半部分和前半部分并不是平行着交叉在一起。再看,前半部分的下标是在递增的,后半部分的下标是在递减的。到这里,你应该可以知道后半部分是在反转之后,再与前半部分进行交叉的。基本上这道题目的思路就是这样,一般来说,链表的题目并不是难在思路上,而是难在具体的实现上面,实在没有思路的话,可以试着把链表当成数组来思考。

解决这道题目有三个步骤,这三个步骤都可以单独拿出来作为链表的考察。第一步是 找链表的中点,这里我们需要用到快慢指针这一技巧,需要注意的是,我们要根据题目的要求来调节快慢指针的起始位置,这个拿几个例子跑跑大概就能知道。第二步是 反转链表,一般来说用普通循环实现的话,需要三个指针交替完成。第三步是 合并链表,这一步相对前两步来说,思考难度会小一点,需要注意的一点是,出了循环,我们仍然要判断。

更具体的,就看代码实现吧。链表相关的题目,主要还是考多练,它的操作其实并不多。


参考代码

public void reorderList(ListNode head) {
    if (head == null || head.next == null) {
        return;
    }

	// 步骤 1: 通过快慢指针找到链表中点
    // 通过调节快慢指针的起始位置,可以保证前半部分的长度大于等于后半部分
    ListNode slow = head, fast = head.next;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }

	// 步骤 2: 反转后半部分的链表
    // 在反转之前需要的一个操作是将前后半部分断开
    ListNode second = slow.next;
    slow.next = null;
    second = reverseList(second);

	// 步骤 3: 合并前半部分链表以及反转后的后半部分链表
    mergeList(head, second);
}

private ListNode reverseList(ListNode head) {
    ListNode prev = null, tmp = null, pointer = head;
    while (pointer != null) {
        tmp = pointer.next;
        pointer.next = prev;
        prev = pointer;
        pointer = tmp;
    }

    return prev;
}

private void mergeList(ListNode first, ListNode second) {
    ListNode dummy = new ListNode(0);
    ListNode pointer = dummy;
    while (first != null && second != null) {
        pointer.next = first;
        first = first.next;
        pointer.next.next = second;
        second = second.next;
        pointer = pointer.next.next;
    }

	// 因为我们之前找中点的时候保证了前半部分的长度不小于后半部分的长度
    // 因此交叉后,多出来的部分只可能是前半部分,判断前半部分即可
    if (first != null) {
        pointer.next = first;
    }
}

Review

Double Your Motivation with This Simple Technique

文章想要解决的问题

这篇文章主要是围绕着 “成本效益” 这个概念展开的。你可能会问,成本效益是什么,感觉上是一个经济学上面的专业名词?其实你可能不知道,平时我们在做决定的时候,大脑都会做一些成本效益的分析。比如说,这个时候是要读书还是追剧;晚饭时间到了,到底是要出去吃还是在家自己弄;到底要不要每天健身;要不要写 ARTS 等等。

当我们对一件事情提不起兴趣的时候,大脑可能就会认为做这件事情的成本是大于收益的,因此大概率上就不会做这件事情。但是大脑默认做的决定有时候是不准确的,下面列出大脑默认做决定的几个误区:

  • 低估了长期来看的成本和效益:就拿健身,读书来说,短期来看去一两次健身房确实不能对你带来可观的收益。可是如果把时间拉长,其收益是巨大的。
  • 高估了小的但是即刻的成本和收益:很好的一个例子就是刷抖音,拿起手机刷抖音的很可能就只是满足你当前的一个小念头,但你依然会放下手头重要的是去做。
  • 低估了一些无形的成本和收益:评判一件事情是否值得去做,需要从多个维度来考虑,比如说,除了那些看得见的收益之外,还需要考虑这件事情对你的,声誉,健康,快乐,是否迎合个人的价值观等等。让大脑默认去做决定,肯定是想不到这方方面面。
  • 低估了机会成本:当你把时间和精力花在一件事情上,其它的事情相对来说就得不到更多的重视。如果不分析一下哪个事情最值得当前做,很可能就会丧失潜在的机会。

上面这些应该是经常能体会到,所以现在我们的问题大概就是如何做成本效益分析,让自己的行动和计划对自己更有益。

分析成本效益的四步骤

文章列出了四个步骤来替代大脑的默认做决定的配置,先来一起看看:

  1. 分别列出你要做的事情的所有可能的成本和收益
  2. 评估这些成本和收益的价值(这里主要评估其对你来说的价值)
  3. 对比上面分析出来的成本和收益
  4. 从所有的事情当中选择一个成本收益比最小的事情作为你接下来要做的事情

有了这四个步骤,你就可以从你每天的 to-do-list 中选择更恰当的事情来做。这四个步骤中,很可能会产生不同的是第二个步骤。因为每个人的经历,阅历不尽相同,因此很可能会得出不一样的结果。想要提高自己评估事情所带来的价值的能力,也只能慢慢经历,慢慢积累了。等到了足够的时间后,也就知道自己最想要什么了。


Tip

继续 vim

这次主要是记录一下 vim 中如何写 markdown 文件,色彩的选择,以及介绍几个插件

用 vim 写 markdown 文件

首先用 避免 写 markdown 文件,离不开 markdown preview 这个插件。这个插件使用起来很直观简洁,官网都有文档,这里就不详细说明。

除了这个插件,还有两个地方需要在 .vimrc 文件中写明,第一个是 tw

set textwidth=72

这个是 vim 中一行显示的最大长度,有些时候电脑很大,如果我们不设定这个的话会让一行的字符数量过于庞大,不利于观看。

另外一个是 formatoptions 这个参数,确保这个参数中含有 tm,前者是保证一行的长度超过 tw,vim 会自动回绕;后者是保证在输入字符是中文的前提下,这个机制依然奏效。


vim 的色彩选择

色彩方面,可以选择自己改写 vim 的脚本文件来达到根据文件类型去控制色彩的选择。当然我们也可以借助于现成的插件,这个就看个人的主观喜好了,我选择了 morhetz/gruvbox 这款插件。用 vim 的插件管理器安装插件后,需要在 .vimrc 文件中选择该插件:

colorscheme gruvbox

该插件的效果图:


Share

这次还是来分享一篇文章,文章很短,可能用不了 5 分钟就可以读完:

恐怕你确定自己喜欢做什么

文章主要阐述了两类事情,一类是自己真的喜欢做的事情,做这类事情可以忘却时间的存在,不管目的是什么,结果又如何,这类事情就是可以给自己带来快乐。另一类事情,是可以带来价值的事情,但是自己不一定喜欢,我们一般都是带有目的性地去做这类事情,这类事情也可以给我们带来快乐,但是并不是因为事情本身给我们带来快乐,而是因为通过做这类事情,我们可以获得一些比较有价值的东西。

如果你问你自己,“什么是你真正感兴趣的事情?” 恐怕一时半会很难给出一个让自己满意的答案。就拿我自己来说,编程算是我感兴趣的事情吗?但很多时候我编程都是带有目的性的,有些时候编程带给我的不是快乐,而是焦虑,所以编程并不能算我真正感兴趣的事情,至少现在不是。写作输出算是我感兴趣的事情吗?想了想,感觉也不是,当初机缘巧合写起了 ARTS,目的也是为了提高自己的技术水平和技术认知,写作虽然给了我很多输出自己的机会,也让自己能够对技术认识的更加全面,但是写作本身并没有给我带来那种忘却时间的快乐。其实你可以看到,上面我说的这两件事情其实都应该属于 “有价值的事情”,这些事情决定着我们的收入,决定着我们的大部分的时间分配,同时也会影响着我们一天的喜怒哀乐。因为这类事情的存在,我们渐渐忘却了什么才是自己真正喜欢的事情,也就是在我们看来真正有意思的事情。

于是,我们更在乎的是如何让自己变得更有价值,而不去在乎如何让自己的生活更有意思。在这种状态下,一旦我们期望的和实际的不相符,我们就会觉得自己什么都不是,生活很没有意思,仿佛这些所谓的有价值的事情可以控制我们的生活,甚至控制我们的所有,导致我们身陷其中而不能自拔。

说了那么多,该如何改变呢?首先我们要有一个恰当的初衷,当我们选择去做一件事情,大可不去在意别人的看法,不去在意这件事情能否为你带来世俗的价值。只要是它能让你开心,让你不去计较得失和结果,给你的生活添增了一些色彩,那么这就是有意思的事情。就拿写 ARTS 来说,我不用去苛求写 ARTS 能给我带来多大的提升,但是每次通过写 ARTS,我都可以去看一些文章,了解一些自己不曾了解的东西,学习一些自己不曾知道的技能,我对世界的了解又多了一点点,这本身就挺有意思。