(这名字起得很像小学生了)

11月28日的时候,我收到了LeetCode的一封邮件,邀请我参加11月30日的第一次LeetCode Internal Contest。这场比赛仅对一小部分内部用户开放,目的是在正式比赛之前确保所有的题目都没有问题。这场比赛不会计入global ranking,参与之后也不能再参加之后的正式比赛。而且参加的用户会发LeetCoin。

我想,这听起来很有趣。虽然我不能去参加正式比赛提高自己的rating了,但是我还是可以比赛,而且还可以给LeetCode提bug,而且还可以获得一些LeetCoin(虽然这年头这些coin也许不像之前的奖励那样吸引人了)。所以我决定去申请一下。

题目出的锅

以我的评价标准,这场比赛并没有出锅;但是赛后有不少参赛者提出了虽然我没看出来但是好像很有道理的意见。正式比赛中修正了一部分内容。正式比赛过后,internel contest的题也都改过了,所以我只能凭借记忆回想题目哪些部分改了。

949. Largest Time for Given Digits

题目地址

这道题基本没出什么问题,虽然有人尝试了一下负数输入,发现标准答案还是输出了一些东西(而不是报错)。这一点目前还没改。我记得有些LeetCode标程是会assert输入的,不过反正测试数据里肯定没有负数输入,所以好像也无所谓。

我感觉很多人应该都在[0,0,0,0]这个输入上错了一次。考察能否想到corner case应该是这一类题的目的之一,我觉得挺好的。不过这要真是一道面试题的话,我可能会说,我在工作环境中会尽可能调用库来处理时间格式

950. Reveal Cards In Increasing Order

题目地址

很多人都表示很喜欢这道题的思考过程。不过我提出的意见是,我读完整道题和样例之后,并没有明白题目到底是要求返回card的一个order,还是index的一个order。当时样例输入还是[1,2,3,4,5,6,7](所以返回index order和card order的结果是相同的)。还有人表示,因为样例输入是递增的,而且题目描述里也提到了“递增”(虽然说的是“……返回使card递增的一种排列”),他以为输入已经是递增的了。现在样例输入已经改成了[17,13,11,2,3,5,7],输出是[2,13,3,11,5,17,7],所以很显然是要求返回card的order(而且输入也不保证是递增的)。

这道题修改的过程使我发觉,样例也是题目的重要组成部分。有些题目里没有说或者没有说清楚的东西可以通过样例来说明,所以选择一组好的样例(既能帮助说明问题,又不泄露题目想要考察的corner case)是很重要的。当然,有时候样例也起到提示一些corner case,降低题目难度的作用(比如一些复杂的模拟题)。

951. Flip Equivalent Binary Trees

题目地址

好像没有什么修改,至少我没看出来。大家都觉得这道题挺好的。不过似乎某一组测试数据中出现了node value重复的情况,现在应该已经改掉了。

952. Largest Component Size by Common Factor

题目地址

这道题的叙述足够清楚(难点在于怎么做,而不在于怎么理解);不过现在的版本相比之前还是为样例加上了示意图,这一点挺好的。

我觉得这道题难(从通过率来看),但是没有那么难(从做法上来说,只要把素数打表和并查集结合起来就可以做了)。我记得这道题的难度分值原来是9分,后来调整到了8分;以及我才注意到,原来每场比赛的难度分值之和是固定的24分。

还有人注意到了这样一种现象:有人的做法复杂度比较高,但是由于比赛时提供出错的测试数据,所以他们可能会通过在特定测试点中直接输出结果来规避大数据,并且通过这种方法来通过整道题。之前比赛中的943. Find the Shortest Superstring也有这种现象。这可能是提供测试数据用来debug的OJ的共有问题。目前我看到的和我想到的解决方案包括:

  • 干脆就不显示数据了
  • 造更多的大数据(>100个),增加特判测试点的难度
  • 增加输出量并限制源程序长度,防止打表
  • 禁止这种行为,鼓励选手举报(我觉得这是个非常馊的主意)
  • 参考其他OJ的赛制,比如在比赛中不测大样例,赛后再测

第二和第三种方案都可以增加跳测试点的难度,但大概并不能完全解决这个问题。至于第一种么……我感觉,LeetCode之所以是LeetCode,而不是CodeForces或者UVa或者POJ,比较关键的一点,就是它是给测试数据的,这一点接近于真实的面试环境,而不是ACM环境。(至于其他的点,我觉得LeetCode的社区环境也不错。)反正我做LeetCode Contest而不是CodeForces Contest的最主要的原因就是比赛时也能调试。(其他原因包括时间固定且合适。)

其他感受

这场比赛有种很social的感觉,每人都要做自我介绍什么的……我也藉此了解了几位题解区常见选手,嗯,大家都很强(而且都挺nice的)。能和他们一起参加这场比赛,我感到很荣幸。

发了1000个LeetCoin。不知道啥时候才能攒到换一件衣服。

今天我发现我的rating掉了(因为在正式比赛里我的成绩算是0分)。我对此感觉不是很满意,不更新rating我觉得是合理的,rating掉了算啥情况。。。

最近听了同学的意见,把日常的Markdown编辑器(或者不如说是博客编辑器)从Atom换成了VScode。可以对它们作如下比较:

  • 启动速度:Atom < VScode(Atom启动总是特别慢,而且会卡死)
  • 资源占用:Atom < VScode(可能是因为实现机制的原因,Atom一直挺能耗CPU和内存的……)
  • 保存配置:Atom << VScode
    • 之所以会有这一条,是因为Atom从七月份之后根本没办法保存我的任何配置……
  • 保存状态:都不怎么样
    • 我弃用Atom的最主要原因是它无法正常保存我的Workspace和Open Editor,每次重启都会发现,它报一堆找不到我七月份的项目的错,而且之前打开的文件列表也回退成七月份的了。经过很多谷歌也没解决这个问题。
    • VScode能正常保存Workspace,而且挺好用的。但它原生好像根本就没有保存Open Editor这个功能。于是我安装了插件Restore Editors,但是它有时候会挂(比如我上次重启的时候)。所以看来每次重启之前我要检查一遍它有没有真的save。
  • 美观程度:差不多,无论哪种看多了都会习惯的

所以我现在觉得我的这个选择还不错。而且我发现VScode对Markdown的插件支持比Atom好(或者你说我没好好探索Atom插件也行……但那可能说明Atom插件不够友好)。比如说,它有一个格式化表格的功能,看起来非常友好:

格式化前

格式化后

但是这种时候人就可能会想要更多的东西。上图中显然英文部分对齐了,但中文部分对不齐,显得有点丑陋(我猜对于强迫症来说应该是极其丑陋吧,还不如不格式化)!问题在于,在(至少是我目前的)VScode的默认字体配置下,中文和英文用的不是同一种字体,虽然英文字体自己等宽,但中文和它不太等宽。

VScode的字体默认配置是Consolas, 'Courier New', monospace。所以现在的中文字体是宋体,英文是Consolas,如果把配置全删掉,就会出现这种效果:

纯默认字体

说实话,我认不出这里的英文是什么字体,但反正我觉得不太好看(而且也不等宽)。monospace不好看,而且也对不齐(而且设置Courier New显示的字体居然和monospace是一样的):

Courier New

于是我又去谷歌了,找到了一个解决方案:更纱黑体(be5invis/Sarasa-Gothic),一种为中文和日语准备的等宽字体。README里只写了一堆怎么build,但事实上作者编译了Release[1],直接下载就行。下载之后会得到一堆ttf文件,直接右键全部安装就行(至少Windows是这样的)。安装完之后在Word的字体库里就能找到各种更纱黑体了,但是在VScode中还不能找到,反正我重启了一遍。

效果是这样的:

更纱黑体

如果font name设置不对,可以参考这个issue:What shoule be the font name of Sarasa Mono that can be used in vscode?

总之,我觉得这个字体看起来还不错,而且终于对齐了,我很高兴。这个字体的对齐方式应该是两个英文字符对齐一个中文字符(比我想象得不愚蠢多了)。不过还是有一些小bug,在我写文章的时候就发现了,是和对齐相关的:

对齐的bug

最右边的“能”字被遮住了大半个。经过实验发现,这个问题可能是省略号导致的。

2018.11.20 UPDATE:作者告诉我等距更纱黑体 SC是Code字体,在这种字体下省略号被当做是half-width character,算是正常表现。Ta叫我去用Term字体,于是换成Sarasa Term SC之后就好了。


  1. https://www.mokeyjay.com/archives/2150