每周完成一个 ARTS:
Algorithm: 每周至少做一个 LeetCode 的算法题
Review: 阅读并点评至少一篇英文技术文章
Tips: 学习至少一个技术技巧
Share: 分享一篇有观点和思考的技术文章
88. Merge Sorted Array
题目:88. Merge Sorted Array
难度:Easy
题意:给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
要求:原地更改 nums1。
解法:
这一题由于有「nums1 和 nums2 都是有序的」这一前提,题目就变得比较简单。要求是将 nums2 插入到 nums1 中,我们就直接对 nums1 进行更改。
我们的思路非常直接,从后往前将 nums2 插入到 nums1 中,挨个比较 nums1[m-1] 和 nums2[n-1] 的元素的大小,如果前者比较大,那么将前者覆盖到 nums1[m+n-1] 的位置,然后 m 自减 1,否则将后者覆盖到 nums1[m+n-1] 的位置,然后 n 自减 1。这样循环到最后,自然就将 nums2 插入到 nums1 中去了。最后,考虑到有可能 nums1 遍历完毕之后,nums2 还没有遍历完,这样的情况下,nums2 中剩下的元素就是两个数组中最小的那几个,由于 nums1 中的所有数字都已经归位,这时候只要将 nums1 中前 n 个数字赋值为 nums2 中剩下的元素即可。另外,如果 nums2 已经遍历完成,n = 0, 那么之前说的替换操作其实也不会执行,这样就可以省去一个「判断 nums2 是否遍历完成」的过程。代码如下
代码:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
while m > 0 and n > 0:
if nums1[m-1] > nums2[n-1]:
nums1[m+n-1] = nums1[m-1]
m -= 1
else:
nums1[m+n-1] = nums2[n-1]
n -= 1
nums1[:n] = nums2[:n]
时间复杂度 O(n),空间复杂度 O(1)。
Math in Data Science, Great Developers Never Stop Learning
本周和大家分享两篇文章。
第一篇文章是 Dataquest 上的一篇文章,名为 Math in Data Science,文章讲解了数据科学几大类常用算法的数学基础,包括:朴素贝叶斯、线性回归、逻辑回归、神经网络、K-Means 聚类和决策树。
文章语言比较简单,涵盖面也已经比较广,可以作为入门读物。
第二篇是 Towards Data Science 上的一篇名为 Great Developers Never Stop Learning 的文章。顾名思义,文章标题意为「伟大的开发者从不停止学习」,那么伟大的开发者都是如何学习的呢?作者给出了自己的方法。
Vim 剪贴板错误缩进的解决办法
在使用 vim 编辑代码的时候,我们经常会遇到这样一个问题:从别处复制来的代码,粘贴到 vim 中之后,代码的缩进就全乱了,像这样:
复制前:
def findmax(a):
if len(a) == 0:
return 0
curr_max = a[0]
for i in a:
if i > curr_max:
curr_max = i
return curr_max
粘贴后:

这种现象一是特别难看,二是针对 Python 这种对缩进敏感的语言是个大坑,因为 Python 使用缩进来区分代码块。
出现这种现象的原因是,很多人在 .vimrc 中都设置了自动缩进的功能,这时候我们需要使用 :set paste 和 :set nopaste 来解决。
在粘贴代码之前使用 :set paste 来设置粘贴模式,效果如下:

但是这样会取消自动缩进的功能,这时候我们再次 :set nopaste 即可。
有的人会问,那这样每次都要切换很麻烦,不想要每次复制粘贴都要敲一段代码,怎么办呢?
这里提供两种思路,一种是使用插件,这个之后我会介绍,第二种就是 share 部分提到的,同步 vim 和系统剪贴板的方式,直接在 normal 模式下使用 p 来进行粘贴。
同步 Vim 与系统剪贴板,同时解决 Vim 没有 clipboard 编译选项的问题
Vim 的剪贴板使用 register(寄存器)的方式,简单来说就是,在 vim 中复制的文本是存储在一个个寄存器中的,粘贴的时候也是将这个寄存器中的文本粘贴进去。使用特定寄存器的时候,我们需要在复制或剪切之前按下 "{register},即「双引号 + 寄存器名称」来引用该寄存器,然后再进行复制或剪切。
举个例子,我们希望复制一段文字到 a 剪贴板,那么我们在复制之前就按下 "a,然后复制,这样就把选中的内容复制到 a 剪贴板了,我们也可以同时使用一个 b 剪贴板来保存另一段文本。
使用 :reg {register} 来查看寄存器中的内容。
粘贴之前引用该寄存器,即可对该寄存器内容进行粘贴。如 "ap 粘贴 a 寄存器中的内容。
系统剪贴板在 vim 中的寄存器默认名为「加号 +」,所以复制之前引用系统剪贴板即可实现与系统剪贴板同步。
下面介绍另外一种简便的方法。
要实现这个功能,需要你的 vim 编译选项中有 clipboard。这里提供两种方式来检查你的 vim 是否有这个功能。
第一种,进入 vim,使用 :echo has('clipboard') 命令,如果返回值是 1,那么说明你的 vim 版本支持这个 feature,直接看下面的配置方法,如果返回值是 0,那么你需要升级你的 vim,或者重新编译安装。
第二种,在命令行输入 vim --version | grep clipboard,如果你的 clipboard 前面是一个加号 +,那么说明你的 vim 版本支持这个 feature,如果是减号 -,则不支持,需要升级你的 vim。
那么如何升级 vim 呢?
这里建议使用 Homebrew 安装。在命令行中输入以下命令:
brew install vim -- --with-override-system-vi
安装完成之后再查看你的 vim 是否支持 clipboard。
这个时候我本人遇到了一个坑,新下载安装的 vim 还是不支持 clipboard。这是因为使用 homebrew 安装的 vim 在 /usr/local/bin/ 这个路径下,而默认的是 /usr/bin/ 路径下的 vim。
在 .vimrc 中添加 alias:
alias vim="/usr/local/bin/vim"
这样你就会使用 homebrew 下载的 vim 来代替默认的 vim 了。
再次检查是否支持 clipboard。
最后,在你的 .vimrc 中添加下面一行即可:
set clipboard=unnamed
重启 terminal 即可。