大家好,我是吴师兄。
最近在某红书上面看到不少账号在宣传一种高科技作弊方式:
用 ai 做笔试题
,操作就是利用两个屏幕,一个屏幕显示考试题目,一个屏幕显示 ai 答案。
演示的很丝滑,但实际上面试官一看就知道再作弊,比如写一道算法题,如果涉及到几个函数,肯定是会来回切换的补充代码,但如果按照 ai 的方式去写,从上到下抄下来,面试官一眼就能看出来。
并且,如果笔试题出的不是 LeetCode 原题,那么用 ai 生成的答案通过率非常低的,反复提问修改都无法通过,否则如果 ai 的通过率很高,我也用不着人工写题解,借助 ai 可以天天发题解文章了。
也就只有问八股文的时候,ai 能给出合理的答案。
...
回归我们公众号的主题。
继续来一道和「大厂秋招」相关的算法原题。
同时,2024 年的大厂真题可以在我的网站上进行练习。
网站地址:
https://oj.algomooc.com/
关注吴师兄,算法学习好轻松
题目描述与示例
题目描述
对于一个连续正整数组成的序列,可以将其拼接成一个字符串,再将字符串里的部分字符打乱顺序。如序列
8 9 10 11 12
,拼接成的字符串为
89101112
,打乱一部分字符后得到
90811211
,原来的正整数
10
就被拆成了
0
和
1
。现给定一个按如上规则得到的打乱字符的字符串,请将其还原成连续正整数序列,并输出序列中最小的数字。
输入描述
输入一行,为打乱字符的字符串和正整数序列的长度,两者间用空格分隔,字符串长度不超过
200
,正整数不超过
1000
,保证输入可以还原成唯一序列。
输出描述
输出一个数字,为序列中最小的数字。
示例一
输入
19801211 5
输出
8
说明
还原出的序列为
8 9 10 11 12
,故输出
8
示例二
输入
432111111111 4
输出
111
说明
还原出的序列为
111 112 113 114
,故输出
111
解题思路
直接从序列
s
中进行判断,较难完成。
考虑到数据量不大,可以通过穷举的方式来完成。
对于
1
到
1000
的数字
num
,考虑长度为
n
的序列
num num+1 num+2 ... num+n-2 num+n-1
将该序列中的每一个数字转化为字符串,再统计每一个数字字符出现的个数,用哈希表
cnt_new
来记录。
原序列
s
中的数字字符,用另外一个哈希表
cnt
来记录。即
for num in range(1, 1001):
cnt_new = Counter()
for i in range(num, num+n):
for ch in str(i):
cnt_new[ch] += 1
或者更加简洁的写法
for num in range(1, 1001):
cnt_new = Counter("".join(str(i) for i in range(num, num+n)))
若发现存在
cnt_new == cnt
,说明此时
num
是所寻找的序列的第一个数字。
这是一种
相对而言比较暴力的解法
,但也足以通过所有用例。
如果想要进一步优化,可以使用
固定滑窗
的做法。
固定长度为序列长度
n
的窗口,对正整数序列
1 2 3 ... 1000
进行滑动,构建一个
win_cnt
表示窗口中各个数字出现的次数。
左边的数字离开,则在
win_cnt
中减去对应的频次;右边的数字加入,则在
win_cnt
中加入对应的频次。
感兴趣的同学可以自行完成上述代码。
参考代码
from collections import Counter
# 属于打乱的字符串s和数字序列长度n
s, n = input().split()
# 将n转换为数字
n = int(n)
# 将序列s中的每一个字符进行统计
cnt = Counter(s)
# 序列最大不会超过1000,故遍历1-1000的所有元素
for