故障键盘
方法一:暴力模拟
比赛直接暴力模拟。
1 | class Solution { |
复杂度分析
- 时间复杂度:\(O(n^{2})\)。
- 空间复杂度:\(O(n)\)。
方法二:双端队列
1 | class Solution { |
复杂度分析
- 时间复杂度:\(O(n)\)。
- 空间复杂度:\(O(n)\)。
判断是否能拆分数组
方法一:正难则反
题目要求将数组拆分为单个元素,因为从拆分角度不太好模拟,所以可以考虑怎么将单个元素合并为整个数组。如果数组长度小于等于 \(2\),则必定满足要求。如果数组长度大于 \(2\),要想将所有元素合并成完整的数组,则必须有一个大于等于 \(m\) 的合并。
1 | class Solution { |
复杂度分析
- 时间复杂度:\(O(n)\)。
- 空间复杂度:\(O(1)\)。
找出最安全路径
纯暴力做法是使用 \(O(n^{2})\) 的时间判断当前点的的安全系数是否大于等于指定的安全系数,总时间复杂度是 \(O(n^{4}\log n)\)。而我在比赛时预处理了一下小偷的位置,最坏情况其实也是 \(O(n^{4}\log n)\),结果通过了,我想大概是因为如果小偷的数量很多,那么 BFS 的限制就多,如果小偷的数量很少,那么 BFS 的限制就少,所以复杂度也不会真的到达最坏情况吧。比较好的做法是多源 BFS + 二分,以每个小偷为起点进行多源 BFS,标记每个位置的最小安全系数,然后在二分的 BFS 时就可以花 \(O(1)\) 的时间判断当前点是否合法。
方法一:多源 BFS + 二分
1 | class Solution { |
复杂度分析
- 时间复杂度:\(O(n^{2}\log n)\)。
- 空间复杂度:\(O(n^{2})\)。
子序列最大优雅度
方法一:贪心
刚看见题目不知道怎么做,想了想动态规划好像不太行,一个是时间复杂度不行,一个是找不到递推关系(感觉)。然后就想这个数据量,可以排序试一下,然后不知怎么就想到正确答案了。首先贪心取利润最大的 \(k\) 个元素,然后每当遇到一个未选过的类别,则用其替换之前的重复类别中的利润最小的元素,每次计算都更新答案。具体分析如下:
- 如果第 \(k+1\) 个元素的类别是重复的,那么使用其替换之前的元素不会使优雅度变大,因为
distinct_categories
不变,并且数组元素按照利润降序排列,所以total_profit
可能会变小或者不变。 - 反之,我们可以尝试使用当前元素替换之前的元素:① 如果替换之前不重复的元素,那么显然不会优雅度不会变大;② 如果替换之前重复的元素,那么肯定优先选择利润最小的重复元素,
distinct_categories
变大,total_profit
变小,优雅度有变大的可能。
反复执行上述操作,就一定可以遍历到最优的情况。比赛时代码很乱,赛后参考了灵神的代码。
1 | class Solution { |
复杂度分析
- 时间复杂度:\(O(n\log n)\)。
- 空间复杂度:\(O(n)\)。