leetcode 第 336 场算法比赛

作者: | 更新日期:

最后一题难道我想复杂了?

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

零、背景

这次比赛前三题用时 11 分钟做完的。
第四题我的思路是线段树加二分,做的慢了点,通过时排两百多名,应该有更简单的方法吧。

比赛源码: https://github.com/tiankonguse/leetcode-solutions/tree/master/contest/3/336

一、统计范围内的元音字符串数

题意:给一个字符串数组,问有多少个字符串收尾字符都是元音。

思路:循环判断即可。

小技巧:元音字符放在 set 容器中,查找即可。

PS:看到 left 和 right,我一度没看懂题,看了好几边才确认题意。

二、重排数组以得到最大前缀分数

题意:给一个数组,可以打乱为任意顺序的数组,问如何打乱,才能是前缀和大于0 的个数最多。

思路:前缀和大于 0 个数最多,显然是正整数放前面,负数放后面,越小的负数需要越往后放。

结论:从大到小排序,统计前缀即可。

三、统计美丽子数组数目

题意:给一个数组,问有多少个美丽子数组。
定义:每次可以选择两个数字,二进制某一位都是1时可以都消为0,如果最终子数组都变为0,则为美丽子数组。

思路:美丽子数组的定义其实就是判断数组的异或值,结果为 0 是,非 0 不是。
所以问题转化为了,有多少个子数组的异或值是 0。

暴力计算复杂度是O(n^2),显然会超时。

不过对于统计满足要求的子数组个数的题型,策略都是计算当前的前缀值,然后判断与之前的前缀值求差,看有多少满足要求。

以区间和为例,sum[1,a] - sum[1,b] 就是 sum[b,a]
asum[b,a] 是输入,求有多少个 b 满足要求。

公式可以转化为 sum[1,a]-sum[b,a],问题就转化为了有多少前缀和 sum[1,b] 满足要求。

异或值类似,可以转化为了统计满足要求的前缀个数。

使用 hash 统计前缀的个数,复杂度O(n)

四、完成所有任务的最少时间

题意:有若干任务,需要在时间区间 [b,e] 内运行 d 秒。
电脑同一时间可以运行无数个任务,问电脑至少运行几秒才能运行到所有任务。

思路:电脑运行任务,很经典的问题,解决方法有很多。

我的思路是贪心,即优先按结束时间向前倒退若干秒,电脑按这个时间运行即可。

要保证贪心的正确性,任务需要先按结束时间从小到大排序。

证明:假设前面的任务已经运行了,对于当前任务,肯定运行的越晚越好,这样时间才能与后面的任务复用时间。

由于前面的任务已经运行了,会与当前任务复用一些时间,所以当前任务结束时间向前倒推时无法直接计算出来。

这里就需要使用一个数据结构和一个算法。
一个数据结构:线段树,用于统计区间内复用了多少时间。
一个算法:二分,找到任务结束时间倒推的边界,倒推的时间区间都需要运行任务,之前的都是复用时间。

PS1:我的线段树模板修改操作是区间都加一个值,而当前问题是复用,所以我浪费不少时间来修改线段树模板。

PS2:二分的时候,有个地方写错了,本来应该写任务区间内的复用时间,我写成二分区间内的复用时间,错误一次。

五、最后

这次比赛的最后一次,我感觉至少有三四种不同的做法。

你都是怎么做的呢?

比赛结束后,我有研究下都有啥解法,放到评论中吧。

第一名:线段树+二分,O(n*log(n)^2) 第二名:暴力循环,O(n^2)
第三名:暴力循环,O(n^2)
第四名:暴力循环,O(n^2)
第五名:区间合并优化,O(n^2)

《完》

-EOF-

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

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

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

tiankonguse +
穿越