华为OD机试真题——阿里巴巴找黄金宝箱(II)(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
2025 A卷 100分 题型
本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》
华为OD机试真题《阿里巴巴找黄金宝箱(II)》:
文章快捷目录
题目描述及说明
Java
python
JavaScript
C
GO
题目名称:阿里巴巴找黄金宝箱(II)
- 知识点:贪心算法、哈希统计、排序
- 时间限制:1秒
- 空间限制:256MB
- 限定语言:不限
题目描述
一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地,藏宝地有编号从0~N的箱子,每个箱子上面贴有箱子中藏有金币的数量。从金币数量中选出一个数字集合,并销毁贴有这些数字的每个箱子,如果能销毁一半及以上的箱子,则返回这个数字集合的最小大小。
输入描述:
一个数字字串,数字之间使用逗号分隔,例如:6,6,6,6,3,3,3,1,1,5
。字串中数字的个数为偶数,且满足:
- 数字个数范围:
1 ≤ N ≤ 100000
- 每个数字范围:
1 ≤ 数字值 ≤ 100000
输出描述:
返回满足条件的最小数字集合大小,例如:2
。
示例:
- 输入:
1,1,1,1,3,3,3,6,6,8
输出:2
说明:选择集合{1,8}
,销毁后剩余[3,3,3,6,6]
,长度为5(超过原数组一半)。
Java
问题分析
我们需要找到一组数字,销毁对应的箱子,使得销毁的箱子数量至少是总数的一半,并且要求这组数字的大小尽可能小。这个问题可以通过统计每个数字出现的频率,并利用贪心算法来高效解决。
解题思路
- 统计频率:使用哈希表统计每个数字的出现次数。
- 排序频率:将频率从高到低排序,优先选择高频数字以快速达到目标。
- 贪心累加:依次累加频率,直到销毁数量满足要求,记录所需的最小数字集合大小。
代码实现
import java.util.*;public class Main {public static void main(String[] args) {// 读取输入并分割成字符串数组Scanner scanner = new Scanner(System.in);String input = scanner.nextLine();String[] parts = input.split(",");int total = parts.length; // 总箱子数int m = total / 2; // 需要销毁的最小数量// 统计每个数字的出现次数Map<Integer, Integer> freqMap = new HashMap<>();for (String part : parts) {int num = Integer.parseInt(part);freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);}// 提取频率列表并按降序排序List<Integer> frequencies = new ArrayList<>(freqMap.values());Collections.sort(frequencies, Collections.reverseOrder());// 贪心累加频率,直到满足销毁数量int sum = 0;int count = 0;for (int freq : frequencies) {sum += freq;count++;if (sum >= m) {System.out.println(count);return;}}// 理论上不会执行到此处System.out.println(count);}
}
代码详解
-
输入处理:
Scanner
读取输入字符串,按逗号分割成字符串数组。total
是总箱子数,m
是需要销毁的最小数量(总数量的一半)。
-
统计频率:
- 使用
HashMap
统计每个数字出现的次数。键是数字,值是出现次数。
- 使用
-
频率排序:
- 将频率值存入
ArrayList
,并按降序排序,便于优先处理高频数字。
- 将频率值存入
-
贪心累加:
- 遍历排序后的频率列表,累加次数直到总和达到或超过
m
,统计使用的数字个数。
- 遍历排序后的频率列表,累加次数直到总和达到或超过
示例测试
示例1:
输入:
1,1,1,1,3,3,3,6,6,8
输出:
2
解析:总共有10个箱子,需要销毁5个。频率排序后为4(1)、3(3)、2(6)、1(8)。累加前两个频率4+3=7≥5,使用2个数字。
示例2:
输入:
6,6,6,6,3,3,3,1,1,5
输出:
2
解析:总共有10个箱子,需要销毁5个。频率排序后为4(6)、3(3)、2(1)、1(5)。累加前两个4+3=7≥5,使用2个数字。
示例3:
输入:
2,2
输出:
1
解析:总共有2个箱子,需要销毁1个。频率为2次,仅需1个数字即可销毁2个箱子,满足要求。
综合分析
- 时间复杂度:O(n log n),其中n为不同数字的个数。排序操作是主要耗时部分。
- 空间复杂度:O(n),用于存储哈希表和频率列表。
- 最优性:贪心算法确保每次选择最优解,能够以最少数字达到目标。
- 适用性:适用于输入规模较大的情况,处理高效且逻辑清晰。
python
问题分析
我们需要找到一组数字,销毁对应的箱子,使得销毁的箱子数量至少是总数的一半,并要求这组数字的大小尽可能小。通过统计每个数字的频率并优先选择高频数字,可以高效解决问题。
解题思路
- 统计频率:用字典统计每个数字的出现次数。