leetcode 第 377 场算法比赛

作者: | 更新日期:

O(1000^2) 的复杂度,莫名其妙超时。

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

零、背景

周六科目二成功考试通过,周日科目三预约的是下午练车,所以上午有时间参加比赛。

这次最后一题是和综合题,但是总体复杂度不高,但是不知为啥总是超时。

A: 排序
B: 预处理垂直线,枚举水平线
C: 全源最短路。
D: hash+全源最短路。

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

一、最小数字游戏

题意:两个人轮流做游戏,每一轮A和B依次移除最小数字,然后B和A依次把数字追加到数组中。

思路:排序,交换相邻数字即可。

二、移除栅栏得到的正方形田地的最大面积

题意:给一个矩阵,现在告诉你若干水平线和垂直线,问是否可以删除一些水平线和垂直线,让剩下的线构成至少一个正方形。
如果可以,返回最大的正方形面积。

思路:如果可以构成正方形,肯定需要两根水平线和两根垂直线。
所以需要枚举两根水平线和两根垂直线。
复杂度:O(n^4)

优化1:上面枚举没有利用正方形的性质。
两根水平线确定后,正方形的边长就确定了。
所以只需要再枚举一根垂直线,另一根垂直线的位置就确定了(上下两个可能)。
复杂度:O(n^3)

优化2:确定正方形边长时,能不能直接判断是否有垂直线答案呢?
预处理垂直线,记录所有可能的边长,即可直接判断。
预处理复杂度:O(n^2)
枚举复杂度:O(n^2)

三、转换字符串的最小成本 I

题意:给一个字符映射到另外一个字符的代价,问原始字符串是否可以替换为目标字符串,求最小代价。

思路:字符只有26个,合并输入映射,可以得到26个字母之间的输入映射代价。
然后通过 floyd 求全源最短路,即可以得到任意两个字母之间的最小映射代价。
复杂度:O(26^3)

之后判断输入字符串是否可以转化为目标字符串即可。

四、转换字符串的最小成本 II

题意:给一个字符串映射到另外一个字符串的代价,问原始字符串是否可以替换为目标字符串,求最小代价。
规则:原始字符串到目标字符串的映射过程中,映射的子串之间不能有交集(相等除外)。

思路:第三题的升级版本。

第一步:对映射的字符串进行hash处理,转化为数字之间的映射,并求全源最短路。
复杂度:O(200^3)

第二步:对原始字符串和目标字符串的所有子串进行预处理,求出对于的hash值。
复杂度:O(1000^2)

第三步:动态规划,枚举判断原始字符串后缀是否可以替换到目标字符串后缀。
方程:dp[i] = min(dp[j-1] + cost[fromHash][toHash] )
复杂度:O(1000^2)

就是这样一个算法,竟然超时了。

全源最短路的复杂度最高。
由于边数最多只有 200 个,于是我不适用 floyd, 改成求每个顶点的最短路。
但源最短路使用 SPFA 堆优化。
复杂度:O(200^2)

最终复杂度:O(1000^2)
但还是超时了。

我把所有 vector 由临时变量调整为全局数组,结果还是超时了。

五、最后

这次比赛最后一题被卡了,看其他人没有使用 hash 字符串,使用二分查找或者 tire 树来做的。
其实 hash 的速度更快,只开了两个O(1000^2)的内存,其他的都是O(200^2)的内存,最终却超时了,莫名其妙。

《完》

-EOF-

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

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

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

tiankonguse +
穿越