Leetcode 第 158 场比赛回顾
作者:
| 更新日期:动态规划题型其实很简单,就是递归记忆化搜索。
本文首发于公众号:天空的代码世界,微信号:tiankonguse
零、背景
十一国庆飞回家了,所以没参加比赛,这周继续。
可能周末只有一天的缘故,一大早起来都没睡醒,比赛就开始了。
还好,这次比赛比较简单,在比赛前全部都做出来了。
不过由于头脑不清晰,有很多地方敲错了,导致 WA 了几次。
尤其是最后一道题,有很多细节。建议大家做做这道题。
一、分割平衡字符串
题意:给一个平衡字符串,问同时可以拆分为多少个子字串,子字串都是平衡字符串。
平衡字符串定义:只有两个字母,且出现次数相等。
思路:从前到后分别统计两个字母出现的次数即可,次数相等时,就可以拆分一个。
证明:原字符串是一个平衡字符串,找到一个平衡字符串前缀时,对应的后缀肯定也是平衡字符串。
所以可以从前到后贪心统计划分。
时间复杂度:O(n)
空间复杂度:O(1)
二、皇后攻击国王
题意:给一个8*8
的棋盘,有一个国王和若干王后,问可以一步攻击到国王的王后个数。
规则:王后横、直、斜都可以走,但是不能跳过其他棋子。
思路:考虑上下左右以及四个斜线,共有 8 个方向。
由于王后不能跳过棋子,所以答案肯定在[0,8]
之间。
第一个方法是枚举国王的这八个方向,看是否可以遇到王后。
第二个方法是枚举所有王后,根据两个棋子的位置看是否在攻击方向上,在了再判断当前方向是否有其他棋子挡路。
由于第二个方法需要作出大量判断,建议使用第一个方法。
三、有限制的掷骰子
题意:每次骰子可以随机的得到1~6
这些数字。
现在需要掷n
次骰子,但是每个数字连续出现的次数有个最大限制。
问此时,可能出现的数字序列有多少个。
思路:典型的动态规划题。
假设当前是起始状态,此时前面是没有依赖,我们可以随机n
次。
掷一次骰子后,可能出现6
个数字其中一个,而下个状态就和前面出现的数字和次数有依赖了,即前面的数字出现的次数需要保存下来。
这里的状态定义为f(k, index, n)
,代表数字index
在前面出现k
次时,再掷n
次骰子会出现多少序列。
那么总答案就是:
ans += f(1, 1, n-1)
ans += f(1, 2, n-1)
ans += f(1, 3, n-1)
ans += f(1, 4, n-1)
ans += f(1, 5, n-1)
ans += f(1, 6, n-1)
那对于有依赖的状态,大概分四种情况。
情况一:n
等于0
了,此时不能掷骰子了,确定一个序列,找到一个答案。
情况二:随机出的数字newIndex
与index
无关,那么得到新的状态f(1, newIndex, n-1)
。
情况三:随机出当前index
,但是还没到达限制,那么得到新状态f(k+1, index, n-1)
情况四:随机出当前index
,但是到达限制,忽略这个状态。
汇总一下就是下面的状态转移方程:
f(k, index, n) = 五个 f(1, newindex, n) + 一个合法的f(k+1, index, n-1)
PS:大家不要纠结这是动态规划还是记忆化搜索了,两个都是,没有冲突的。
动态规划是一种拆分子问题的思想,记忆化搜索是这种思想的递归实现。
四、最大相等频率
题意:给一个数组,问是否存在某个前缀,删除一个元素后,剩余的元素按值分组个数相等。
如果存在,返回最大的前缀长度。
思路:起初看到整道题,惊呼这么简单的题怎么是最后一题呢。
做了之后才发现,这道题有毒,需要考虑很多边界,也需要优化时间复杂度。
这道题的处理流程很简单,枚举所有前缀,判断是否是满足要求。
那什么时候是答案呢?
大概分几种情况:
情况一:只出现一个数字,显然是答案。
7 7 7 7 7
情况二:出现很多数字,但是都次数都是1。
7
8
9
情况三:只有一个数字出现一次,其他都出现多次,且次数相等。
6
7 7 7
8 8 8
9 9 9
情况四:所有数字都出现多次,但是大多数次数都相等,只有一个特殊多了一次。
7 7 7 7
8 8 8
9 9 9
能想到这里,一般这道题就可以考虑到所有边界,从而不会 WA 了。
但是还会超时。
因为我们是枚举每个前缀的O(n)
,每个前缀又需要进行分组,复杂度O(n)
,合起来就是O(n^2)
的复杂度了。
那该怎么优化呢?
前缀是一个好的模式,因为前缀n
和前缀n+1
是有关系的。
我们计算前缀n+1
时,完全可以想办法利用上前缀n
的计算结果,从而避免重复计算。
所以优化方式就是,维护一个前缀分组。
时间复杂度:O(n log(n))
PS:每次用到map
的时候,就会有人提到可以使用hash map
,时间复杂度是O(1)
的。
这里大家不要纠结这个了。
五、最后
这次比赛的题相对来说还算简单,都是我擅长的数据结构题。
你学会了吗?
-EOF-
本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code
本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。