每周完成一个 ARTS:
Algorithm: 每周至少做一个 LeetCode 的算法题
Review: 阅读并点评至少一篇英文技术文章
Tips: 学习至少一个技术技巧
Share: 分享一篇有观点和思考的技术文章
题图:尼斯蓬切茨公共海滩,photo by me
难度:Easy
题意:Reverse a singly linked list.
示例:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
解法:
使用递归方法,先来看代码。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head is None or head.next is None:
return head
last = self.reverseList(head.next)
head.next.next = head
head.next = None
return last
分析递归代码,不要跳进递归里,而应该根据函数定义来弄清楚这段代码产生的结果。
逐行分析这段代码:
last = self.reverseList(head.next)
这一行将头结点之后的部分全部翻转过来了,而(顺序的)第二个节点的 next 指向空;head.next.next = head
则将第二个节点的 next 指向了第一个结点;head.next = None
把第一个节点的 next 指向空。这样就反转了整个链表。我们接下来看第二道题。
难度:Medium
题意:
Reverse a linked list from position m to n. Do it in one-pass.
Note: 1 ≤ m ≤ n ≤ length of list.
示例:
Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL
解法:
对于这一题,我们先来设想一个反转前 n 个元素的函数 reverseN(head, n)
。它可以反转链表的前 n 个元素,并返回第 n 个元素的节点:
def reverseN(head: ListNode, n: int) -> ListNode:
if n == 1:
return head
last = reverseN(head.next, n-1)
successor = head.next.next
head.next.next = head
head.next = successor
return last
分析一下这段代码:
head.next
开始索引的话,需要反转的就是 n-1 个元素;head.next
其实就是第二个元素,而 head.next.next
指向的则是第 n+1 个元素(后驱节点);最后回到这道题本身,如果 m == 1
,那么就相当于从头开始反转 n 个元素;如果 m != 1
,那么对于 head.next
来说就是反转 m - 1
个元素,以此类推,我们可以递归地调用这段代码本身……
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
successor = None
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
def reverseN(head: ListNode, n: int) -> ListNode:
if n == 1:
return head
last = reverseN(head.next, n-1)
successor = head.next.next
head.next.next = head
head.next = successor
return last
if head is None or head.next is None:
return head
if m == 1: return reverseN(head, n)
head.next = self.reverseBetween(head.next, m - 1, n - 1)
return head
本周阅读的文章来自 DailyIO 的推荐,来自 Real Life 杂志的《Rank and File - What if my note-taking system could think for me?》。作者在这篇文章中,回顾了他从大学时代开始使用笔记工具的历程,他没有使用很多不同种类的工具,但尝试了多种思路之后,作者最后的发现是:
I had misplaced the focus and meaning of intellectual activity onto the act of taking notes, like someone deciding that the point of eating was the gurgling metabolic activity of their stomach rather than either the taste of food or the effect of nutrition.
包括笔记工具在内的任何工具都不应该是做事的目的。
Notion 提供了浏览器的插件,来帮助我们实现对网页的收藏功能,这个功能其实蛮好用的,但缺点在于,Notion 的插件默认爬取的是网页中的第一大段,一个简单的例子就是在论坛里,Notion 只能爬取一楼的内容,无法指定获取想要的楼层。
简悦的阅读模式可以克服这个问题,只需要在使用简悦生成阅读页面时选择想要保存的部分,再从简悦提供的动作中选择「保存到 Notion」即可。
在《把时间当作朋友》中,李笑来记述了他自己、李敖和柳比歇夫的时间记录方式以及它们的不同,我随即也认识到时间记录的重要性。
记录时间的好处有下面几点:
但是最大的问题在于,人们即便意识到了记录时间的好处,也不愿意去记录时间。我不知道我的读者中有多少人有记账的习惯,但是不愿意记录时间的原因我们可以类比一下记账:
由于自己从大概一年前开始就有记账的习惯,并且保持了下来,在思考了自己在记账前做的几项准备之后,我发现了以下几点:
基于此,我很快在少数派上找到了一篇和我的记账思路非常类似的记录时间的文章《郝海龙:走出时间记录的盲区》,文章中提到了几点:
从 2 月 3 日开始尝试记录自己的时间,几天之后,记录在案的时间达到了 118 小时(5 天一共 120 小时):
从以上这一份分析中,可以发现以下几点:
其他更细致的数据还需要对照每天的时间记录进行挖掘,暂时先想这么多,欢迎在评论区留言讨论~