leetcode 第188算法比赛

作者: | 更新日期:

发现手速与脑速都跟不上了。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

零、背景

有几周没参加比赛了。

记得刚有 leetcode 中文网站的时候,我就去使用了下,结果比赛被中文错误的翻译坑了几次,就再也不在中文 leetcode 做比赛了。

现在已经过了几年了,这些问题 leetcode 中文网应该都解决了。

另外中文网站有一个好处,就是网站速度比英文快,而且题目阅读起来也轻松很多,那为什么不来中文网站呢。

这周开始,我准备在中文 leetcode 上做比赛,在中文 leetcode 上做题。

好了,接下来看看这次比赛的题目吧。

一、构造数组

题意:给一个有序的目标数组栈,有一个输入流,依次从1~n返回一个数字,问怎么构造出目标数组。
输入流操作:我们可以把输入流的数字入栈目标数组,也可以选择出栈。
如果已经构造出目标数组,则可以结束。
求入栈出栈的操作序列。

题目比较抽象,看个例子就懂了。

假设目标数组是1,3,输入流是1~4
第一次来的是 1,入栈 push。
第二次来的是 2,入栈 push,由于目标数组不需要 2,需要再次 pop 出栈。
第三次来的是 3,入栈 push。
构造出目标数组了。

思路:

每次比较当前输入流的数字是否需要保留在目标数组中,不需要则 push 和 pop 二连操作。
需要保留在目标数组中,则只 push 即可。

二、三元组数目个数

题意:给一个数组,问是否存在三个下表i<j<=k,使得 XOR(i,j-1)XOR(j, k) 相等。
XOR(x,y) 含义是 x 到 y 之间的数字进行异或操作。

分析:

异或的第一个性质:相同的值异或后为 0。
异或的第二个性质:满足结合律,即 (a ^ b) ^ ca ^ (b ^ c) 相等。

这两个性质可以推出一个结论:对于任意 j, XOR(i, j-1) ^ XOR(j,k) 都和 XOR(i,k)相等。

由此,我们如果找到一个XOR(i,k)为0,则可以拆分为 k-i个 j 构造出三元组。

这样,我们只需要找到所有的二元组 (i,k),使得XOR(i,k) 为0,然后使用上面的公式计算出有多少个三元组即可。

坑:我看错题意了,看成i<j<k了,花费不少时间。

三、收集苹果的最少时间

题意:给一个无向树,某些节点上有苹果。
求从 0 节点出发,把所有苹果摘掉后,再返回 0 节点的时间。
时间:每经过一条边,消耗 1 秒。

分析:DFS 即可。

注意1:如果某个儿子没有苹果,就没必要遍历那个儿子。
注意2:边下去和上来都消耗时间。

如果父节点下的某个儿子有苹果,父亲到儿子需要加上往返的代价。
那这个代价在哪里处理就需要作出抉择:

一种是儿子自己负责判断当前子树是否有苹果。
一种是父节点负责判断儿子是否有苹果。

我采用的是儿子自己判断。
此时注意事项是根节点没有父节点。

如果采用父节点判断,则需要额外增加一个变量来标记儿子上是否有苹果。

四、切披萨的方案数

题意:给一个披萨矩阵,需要将披萨切成 k 分,每份上至少有一个苹果。问有多少种切法。
规则:上下切的时候,只能切下面,上面的不能切。左右切的时候,只能切右边,左边不能切。

思路:标准的动态规划。

定义状态:f(x,y,k) 为子矩阵 (x,y) 分给 k 个人的答案。
则对于第一个人,枚举所有横着切和竖着切的方法,对于合法的方案求和即可。

合法的条件:第一个人切后有苹果,剩下的矩阵存在方案,分给 k - 1个人。

剪枝:如果矩阵剩余的苹果小于人数,那肯定不符合条件的。
出口:如果只剩一个人时,有苹果则存在一个方案,否则不存在方案。


五、最后

这次比赛我犯了不少错误。

第二题构造三元数组,我看错题了,浪费不少时间。
第三题摘苹果,来回我只算了一次时间,也算看错题了。
第四题则是手误,预处理时从后到前处理的,我的迭代器写成 ++ 了。

看来自己还是需要注意这些细节的,细节决定了我能不能进去前50 名把。

思考题:这次摘苹果和披萨题是否有遇到什么问题了吗?

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越