米哈游笔试思路分享(2025-03-08)

第一题

送分题,模拟


第二题

解答题目意思,需要找到字符串的两个子串(长度>2)是回文字符,返回任意两个回文子串的区间即可


思路一 动态规划

用f[i][j] 表示 [i, j]区间子串是不是回文串

状态转移方程:if s[i] == s[j]: f[i][j] = f[i + 1][j - 1]

如何递推?

普通的dp递推一般是按照方程从前往后递推或者从后往前递推,但是注意到这里的方程里有 i + 1, j - 1 一个往前,一个往后。两个方向都不行,怎么办呢?

  • 可以使用队列来递推,比如队列里先保存[i, j], 取出[i, j]后往两边递推,既看[i - 1, j + 1]满不满足回文,是回文的话就放入队列

如何初始化?

考虑单数和偶数情况

  • 单数情况下初始情况为单个字符,单个字符肯定是回文,需要把所有单个字符全部放入队列,既[i, i] (for i in [0, s.length])
  • 偶数情况下初始情况为0个字符,肯定是回文,全部放到队列即可,注意区间取值[i, i - 1] (for i in [1, s.length])

优化

题目只需要任意两个回文子串,所以我们找到两个后就可以提前结束


思路二 暴力 + 剪枝

直接暴力枚举 4个坐标 + 判断回文 是会超时的,可以进行一些优化

我们可以剔除一些明显不满足题意的情况,例如我们枚举[i, j, m, n] 四个坐标

  • 当[i, j] 区间不为回文时,[m, n]就不需要枚举了

对于判断字符串是不是回文,可以用双指针

最终伪代码如下

for(i in [0, s.length - 3))
	for(j in [i + 1, s.length - 2))
		if(check(i, j)){ // 检查[i, j]是不是回文
			for(m in [j + 1, s.length - 1)){
				for(n in [m + 1, s.length)){
					if(check(m, n)){
						return {i, j, m, n};
					}
				}
			}
		}

顺带一提,我发现暴力还比第一种思路耗时会小些


第三题

n个字符串, 需要两两判断,看两个字符串同一个位置字符差异个数是否小于k,小于k就可以放到同一个集合

可以使用并查集,先两层遍历判断两个字符串差异值是否小于k,小于的话就合并

最终看并查集里面最大的集合的个数m是不是等于字符串个数n

  • 是的话,输出YES
  • 不是的话,说明有多个集合,输出NO, 保留最大的集合满足最小操作次数,既 (n - m)

最后,如果对你有用的话,求个花花
全部评论
第二题先把回文串的边界的集合都找到,按照第一个数大小排序,排除长度小于2的,边界范围,排除相邻的边界不是严格递增的,排除空集合。然后随便输出两个就好了
点赞 回复 分享
发布于 03-09 15:33 安徽
所有技术岗都是一套题目吗
点赞 回复 分享
发布于 03-10 16:37 新疆

相关推荐

评论
2
收藏
分享

创作者周榜

更多
正在热议
更多
牛客网
牛客企业服务