最近后台好几个准备秋招的同学来问华为那道“相册重复图片检测”的机考题,尤其集中在通用软件和嵌入式方向。这道题被放在非AI方向的第一题,100分,题目本身不算难,但很能看出一个人的基本功:会不会用哈希表、能不能稳准狠地处理输入输出、知不知道什么时候该排序。很多人一看名字里有“图片”两个字就开始慌,其实它考的根本不是图像处理。这篇文章我会把题目还原成可复现的版本,然后用Java、C++、Python各写一遍完整题解,再讲讲我实际操作中踩过的各种坑。不管你是刚配好Java环境的新手,还是正在VSCode里调C/C++环境准备刷题的选手,这篇解析都能直接用上。
1. 题目场景与考点拆解
1.1 题目长什么样
华为机考的题目描述一般不会特别长,但会包一层现实场景的外壳。这道“相册重复图片检测”,核心场景就是手机相册里存了大量照片,某一张照片可能在相册里重复出现多次,要求你把所有重复的照片找出来。
因为机考环境不可能真的给你图片文件,所以题目通常会把图片抽象成一个字符串ID。下面是我按历年机考常见形式还原出来的题目描述,各批次细节可能略有出入,但核心逻辑是一样的:
text复制输入描述:
第一行一个正整数 N,表示图片数量。
接下来 N 行,每行一个字符串,表示一张图片的ID。
ID由小写字母和数字组成,长度不超过20。
限制:1 <= N <= 100000
输出描述:
按字典序升序输出所有出现次数大于1的图片ID,每个ID占一行。
如果没有任何重复图片,输出 NO。
比如输入:
text复制6
abc123
def456
abc123
ghi789
def456
abc123
输出应该是:
text复制abc123
def456
因为 abc123 出现3次,def456 出现2次,而 ghi789 只出现1次,不算重复。注意输出顺序必须是字典序升序,不是按出现次数排,也不是按输入顺序排。
这种题目在机考里非常常见,它把“图片重复检测”抽象成了“字符串频率统计”。所以你别被“相册”两个字带偏,本质上就是给一堆字符串,让你统计频次。后面如果题目描述变成“文件名重复检测”“URL重复检测”,做法一模一样。
1.2 这道题到底在考什么
我后来复盘这道题,发现它作为第一题是有用意的,考察点非常集中,几乎不整花活:
- 哈希表的基本使用。能不能想到用哈希表统计频次,是这道题的第一道分水岭。
- 字符串处理能力。读入字符串、判断相等、按字典序排序,都是最基础的字符串操作。
- 时间复杂度的估计。如果只会两层循环暴力比较,N到10万时直接超时,这题就废了。
- 输出格式的严谨性。有没有重复都要有输出,重复ID不能重复输出,顺序必须是字典序。
另外,题目括号里写了“通软&嵌软&测试&算法&数据科学”,很多同学看到“数据科学”就觉得要考机器学习、图像识别,其实完全不是。非AI方向的机考第一题,不管投的是哪个岗位,考察的都是通用编程能力。数据科学岗位也不例外,第一题照样是基础数据结构,不会让你上模型。这一点想清楚,心态就能稳住。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路的演进与选择
2.1 最直白的暴力法为什么不行
正常人看到“找重复”的第一反应是两两比较:拿第一张图片和后面所有图片比,第二张再往后比,遇到相同就记下来。这个思路没有错,但复杂度完全不可接受。
假设每次比较两个ID字符串平均需要花L的时间,L大概是20以内,那总的比较次数是 N*(N-1)/2。当N=100000时,比较次数接近50亿次。哪怕每次比较很快,50亿这个量级在现代评测机上也是铁定超时的。
我用一个生活化类比解释给朋友听:这就像让一万个人互相握手,每个人都要问对方“你手里的照片和我一样吗”,最后要问接近五千万次。题目只给你1到2秒运行时间,根本不可能完成。所以暴力法虽然能想出来,但永远不该出现在提交代码里。
2.2 哈希表解法:一次遍历搞定
正确做法是把所有ID放进哈希表里,以ID为键、出现次数为值,边遍历边统计。
- 第一步,遍历所有图片ID,执行
map[id]++。 - 第二步,遍历哈希表,把次数大于1的ID收集到一个列表里。
- 第三步,对列表按字典序排序。
- 第四步,如果列表为空输出
NO,否则逐行输出。
时间复杂度是 O(N + U log U),其中 U 是去重后的ID数量。最坏情况下 U 最多等于 N,所以整体是 O(N log
