leetcode 第 266 场算法比赛
作者:
| 更新日期:这题出的,该通过的算法被卡超时,暴力的方法直接过了。
本文首发于公众号:天空的代码世界,微信号:tiankonguse
零、背景
这次比赛题目该怎么办说呢?
第三题 n log(n)
的方法被卡超时,浪费不少时间重新敲另外一个方法。
第四题花了不少时间做剪枝优化并通过,赛后优化都删掉,暴力 Dfs 竟然也通过了。
一、统计字符串中的元音子字符串
题意:给一个字符串,问由纯元音字母组成且包含所有元音的子字符串个数有多少个?
思路:数据范围不大,双层循环枚举所有子串即可。
复杂度:O(n^2)
优化:对于每个双元音连续子串,使用双指针快速判断满足要求的子串个数。
复杂度:O(n)
二、所有子字符串中的元音
题意:给一个字符串,问所有子串中,元音字母出现的次数。
思路:原问题是求所有子串所有元音出现的次数。
可以分别求每个位置的元音在哪些子串中出现过,所有位置的元音出现的次数之和就是答案。
一个元音出现的子串为左半部前缀的个数乘以右半部后缀的个数。
复杂度:O(n)
三、分配给商店的最多商品的最小值
题意:给 m 种类的商品,每类有若干个。现在需要把所有商品分配给 n 个商店。
每个商店只能分一类商品,问怎么分配,才能使得分配给商店的最大商品个数最小。
思路:我简单一分析,发现一个优先队列的贪心方法。
策略:默认把 m 个商品分给 m 个商店,即每个商品只分配给一个商店。
如果还有剩余商店,取平均分分配后,商品个数最多的那个商品,这个商品的商店个数加一,平均均就可以变小了。
这样不断的把商店分配给商品,最终就可以使答案最优。
时间复杂度:O(n log(n))
内存复杂度:O(m)
这个敲完后超时了,显然是因为内存操作太多,常数太高,被卡内存了。
回头一想,求最大值的最小值,显然使用二分查找可以做。
然后就把代码都删了,二分最优值,求出最少需要的商店个数,几行代码就写完了。
时间复杂度:O(n log(maxVal))
内存复杂度:O(1)
思考:猜测被卡超时的另一个原因是 leetcode 数据样例的 maxVal 都比较小,商品和商店的个数比较多。
四、 最大化一张图中的路径价值
题意:给一个无向图,每个边有一个时间代价,每个顶点有一个价值。
问从 0 出发,在 maxTime 时间内返回 0 时,经过的顶点的最大累计价值。
思路:数据上有两个突破口。
第一是:每个节点 至多 有 四条 边与之相连。
这意味者暴力计算时,每次顶多分叉四次。
第二是时间范围都在 [10, 100]
之间。
这意味者去在回来,顶多有 10 跳。
分叉四次,10 跳,复杂度就是 O(4^10)
,不会超时。
leetcode 的复杂度是最让人搞不懂的,我怕被卡超时,就进行剪枝优化。
预处理每个节点到 0 节点的最低耗时,这样枚举过程中,先判断是否可以在时间范围内返回 0 点。
PS:所有题通过后,我把剪枝删除后,暴力的代码只有几行,依旧可以通过。
五、最后
这次比赛第三题贪心是挺不错的策略,却被卡超时。
最后一题剪枝本来是个好思路,结果暴力就可以过。
打 Leetcode 比赛的时候,到底要不要优化真的把握不准,就像抽奖一样。
对于要不要优化,你有什么经验要分享的吗?
加油,算法人。
《完》
-EOF-
本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code
本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。