2025 A卷 200分 题型
本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析;
并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式!
2025华为OD真题目录+全流程解析/备考攻略/经验分享
华为OD机试真题《攀登者2》:
目录
- 题目名称:攀登者2
- 题目描述
- Java
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 测试示例
- 综合分析
- python
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- JavaScript
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- C++
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- C语言
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- GO
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
题目名称:攀登者2
知识点:动态规划、贪心算法
时间限制:1秒
空间限制:256MB
限定语言:不限
题目描述
攀登者喜欢寻找各种地图并尝试攀登到最高的山峰。地图表示为一维数组,数组的索引代表水平位置,数组元素代表海拔高度(0为地面)。一个山脉可能包含多个山峰(高度大于相邻位置或位于边界且高于相邻位置)。登山时体力消耗规则如下:
- 上山:相邻高度差的两倍体力
- 下山:相邻高度差的一倍体力
- 平地:不消耗体力
攀登者需评估在给定体力下能安全返回地面的可攀登山峰数量(体力耗尽时有生命危险)。
输入描述
- 第一行为地图数组(如
0,1,4,3,1,0
) - 第二行为攀登者体力值
输出描述
- 可安全攀登山峰的数量
示例
输入:
0,1,4,3,1,0,0,1,2,3,1,2,1,0
13
输出:
3
说明:可攀登至索引3、10、12的山峰,且总体力消耗均小于13。
Java
问题分析
我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并安全返回所需的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计可安全攀登山峰的数量。
解题思路
- 识别山峰:遍历数组,找到所有符合山峰条件的位置(高度大于相邻位置或位于边界且高于相邻位置)。
- 预处理最近地面:对于每个位置,找到其左边和右边最近的地面(值为0的位置)。
- 计算体力消耗:对每个山峰,计算从左边或右边地面出发并返回的最小体力消耗。
- 统计有效山峰:比较每个山峰的体力消耗与给定体力值,统计可安全攀登的山峰数量。
代码实现
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int[] map = Arrays.stream(scanner.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();int energy = Integer.parseInt(scanner.nextLine());List<Integer> peaks = new ArrayList<>();// 1. 找出所有山峰for (int i = 0; i < map.length; i++) {boolean isPeak = false;if (i == 0) {isPeak = map[i] > map[i + 1];} else if (i == map.length - 1) {isPeak = map[i] > map[i - 1];} else {isPeak = map[i] > map[i - 1] && map[i] > map[i + 1];}if (isPeak) {peaks.add(i);}}// 2. 预处理每个位置的左右最近地面int[] leftGround = new int[map.length];int[] rightGround = new int[map.length];int lastZero = -1;for (int i = 0; i < map.length; i++) {if (map[i] == 0) {lastZero = i;}leftGround[i] = lastZero;}lastZero = -1;for (int i = map.length - 1; i >= 0; i--) {if (map[i] == 0) {lastZero = i;}rightGround[i] = lastZero;}int count = 0;// 3. 计算每个山峰的最小体力消耗for (int peak : peaks) {int left = leftGround[peak];int right = rightGround[peak];if (left == -1 && right == -1) continue;int minEnergy = Integer.MAX_VALUE;if (left != -1) {int go = calculateEnergy(left, peak, map);int back = calculateEnergy(peak, left, map);minEnergy = Math.min(minEnergy, go + back);}if (right != -1) {int go = calculateEnergy(right, peak, map);int back = calculateEnergy(peak, right, map);minEnergy = Math.min(minEnergy, go + back);}if (minEnergy <= energy) {count++;}}System.out.println(count);}// 计算从start到end的体力消耗private static int calculateEnergy(int start, int end, int[] map) {int energy = 0;if (start < end) {for (int i = start; i < end; i++) {int diff = map[i + 1] - map[i];if (diff > 0) {energy += 2 * diff;} else if (diff < 0) {energy += -diff;}}} else {for (int i = start; i > end; i--) {int diff = map[i - 1] - map[i];if (diff > 0) {energy += 2 * diff;} else if (diff < 0) {energy += -diff;}}}return energy;}
}
代码详细解析
- 读取输入:将输入的地图数组和体力值转换为Java数组和整数。
- 识别山峰:遍历数组,根据位置判断是否为山峰(边界或高于相邻位置)。
- 预处理最近地面:
leftGround[i]
:记录位置i左边最近的地面(值为0的位置)。rightGround[i]
:记录位置i右边最近的地面。
- 计算体力消耗:
- 对每个山峰,计算从左地面到山峰再返回的体力消耗和从右地面到山峰再返回的体力消耗。
- 使用
calculateEnergy
方法计算路径的体力消耗,考虑上山(2倍高度差)和下山(1倍高度差)。
- 统计有效山峰:比较每个山峰的最小体力消耗与给定体力值,统计符合条件的数量。
测试示例
示例输入:
0,1,4,3,1,0,0,1,2,3,1,2,1,0
13
输出:
3
解析:山峰索引为2、9、11。计算各自的体力消耗均小于13,故输出3。
综合分析
- 时间复杂度:
- 识别山峰:O(n)
- 预处理地面:O(n)
- 计算体力:最坏O(n^2)(每个山峰遍历整个数组),但实际中路径长度较短。
- 空间复杂度:O(n)存储地图和预处理数组。
- 优势:通过预处理地面位置,减少重复计算;体力计算明确区分上山和下山,确保准确性。
- 适用性:适用于路径长度较短或山峰数量较少的情况,处理大规模数据时可能需优化。
python
问题分析
我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并安全返回所需的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计符合条件的山峰数量。
解题思路
- 识别山峰:遍历数组,找到符合条件的位置(高度大于相邻位置或位于边界且高于相邻位置)。
- 预处理最近地面:对于每个位置,预处理其左边和右边最近的地面(值为0的位置)。
- 计算体力消耗:对每个山峰,计算从左边或右边地面出发并返回的最小体力消耗。
- 统计有效山峰:比较每个山峰的体力消耗与给定体力值,统计符合条件的数量。
代码实现
def main