每周完成一个 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 即可。