华为OD机试真题——攀登者2(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

在这里插入图片描述

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

问题分析

我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并安全返回所需的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计可安全攀登山峰的数量。


解题思路

  1. 识别山峰:遍历数组,找到所有符合山峰条件的位置(高度大于相邻位置或位于边界且高于相邻位置)。
  2. 预处理最近地面:对于每个位置,找到其左边和右边最近的地面(值为0的位置)。
  3. 计算体力消耗:对每个山峰,计算从左边或右边地面出发并返回的最小体力消耗。
  4. 统计有效山峰:比较每个山峰的体力消耗与给定体力值,统计可安全攀登的山峰数量。

代码实现

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;}
}

代码详细解析

  1. 读取输入:将输入的地图数组和体力值转换为Java数组和整数。
  2. 识别山峰:遍历数组,根据位置判断是否为山峰(边界或高于相邻位置)。
  3. 预处理最近地面
    • leftGround[i]:记录位置i左边最近的地面(值为0的位置)。
    • rightGround[i]:记录位置i右边最近的地面。
  4. 计算体力消耗
    • 对每个山峰,计算从左地面到山峰再返回的体力消耗和从右地面到山峰再返回的体力消耗。
    • 使用calculateEnergy方法计算路径的体力消耗,考虑上山(2倍高度差)和下山(1倍高度差)。
  5. 统计有效山峰:比较每个山峰的最小体力消耗与给定体力值,统计符合条件的数量。

测试示例

示例输入

0,1,4,3,1,0,0,1,2,3,1,2,1,0  
13  

输出

3

解析:山峰索引为2、9、11。计算各自的体力消耗均小于13,故输出3。


综合分析

  1. 时间复杂度
    • 识别山峰:O(n)
    • 预处理地面:O(n)
    • 计算体力:最坏O(n^2)(每个山峰遍历整个数组),但实际中路径长度较短。
  2. 空间复杂度:O(n)存储地图和预处理数组。
  3. 优势:通过预处理地面位置,减少重复计算;体力计算明确区分上山和下山,确保准确性。
  4. 适用性:适用于路径长度较短或山峰数量较少的情况,处理大规模数据时可能需优化。

python

问题分析

我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并安全返回所需的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计符合条件的山峰数量。


解题思路

  1. 识别山峰:遍历数组,找到符合条件的位置(高度大于相邻位置或位于边界且高于相邻位置)。
  2. 预处理最近地面:对于每个位置,预处理其左边和右边最近的地面(值为0的位置)。
  3. 计算体力消耗:对每个山峰,计算从左边或右边地面出发并返回的最小体力消耗。
  4. 统计有效山峰:比较每个山峰的体力消耗与给定体力值,统计符合条件的数量。

代码实现

def main():import sysinput = sys.stdin.read().split()map = list(map(int, input[0].split(',')))energy = int(input[1])n = len(map)# 预处理左边最近地面和累计绝对差left_ground = [-1] * nleft_sum = [0] * ncurrent_ground = -1current_sum = 0for i in range(n):if map[i] == 0:current_ground = icurrent_sum = 0else:if current_ground != -1 and i > 0:current_sum += abs(map[i] - map[i-1])left_ground[i] = current_groundleft_sum[i] = current_sum# 预处理右边最近地面和累计绝对差right_ground = [-1] * nright_sum = [0] * ncurrent_ground = -1current_sum = 0for i in range(n-1, -1, -1):if map[i] == 0:current_ground = icurrent_sum = 0else:if current_ground != -1 and i < n-1:current_sum += abs(map[i+1] - map[i])right_ground[i] = current_groundright_sum[i] = current_sum# 找出所有山峰peaks = []for i in range(n):left_ok = (i == 0) or (map[i] > map[i-1])right_ok = (i == n-1) or (map[i] > map[i+1])if left_ok and right_ok and map[i] > 0:peaks.append(i)count = 0for peak in peaks:l = left_ground[peak]r = right_ground[peak]min_cost = float('inf')if l != -1:min_cost = min(min_cost, left_sum[peak] * 3)if r != -1:min_cost = min(min_cost, right_sum[peak] * 3)if min_cost <= energy:count += 1print(count)if __name__ == "__main__":main()

代码详细解析

  1. 输入处理:读取输入并转换为整数数组和体力值。
  2. 预处理左边地面
    • left_ground[i] 记录位置 i 左边最近的地面索引。
    • left_sum[i] 记录从左边地面到 i 的绝对差累计和。
  3. 预处理右边地面
    • right_ground[i] 记录位置 i 右边最近的地面索引。
    • right_sum[i] 记录从 i 到右边地面的绝对差累计和。
  4. 识别山峰:遍历数组,判断每个位置是否为山峰。
  5. 计算体力消耗:对每个山峰,计算左右路径的最小体力消耗(绝对差和 ×3)。
  6. 统计结果:比较消耗与体力值,统计符合条件的山峰数量。

示例测试

示例输入

0,1,4,3,1,0,0,1,2,3,1,2,1,0
13

输出

3

解析:三个山峰(索引3、10、12)的体力消耗分别为9、9、9,均小于13。


综合分析

  1. 时间复杂度

    • 预处理:O(n) 两次遍历数组。
    • 识别山峰:O(n) 遍历数组。
    • 总复杂度:O(n),高效处理大规模数据。
  2. 空间复杂度

    • 存储预处理数组:O(n),空间复杂度线性。
  3. 优势

    • 预处理优化:避免重复计算,快速获取路径信息。
    • 贪心策略:选择左右路径中的最小值,确保最优解。
  4. 适用场景

    • 处理一维数组中的山峰覆盖问题,尤其适合大规模数据。

JavaScript

问题分析

我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并安全返回所需的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计符合条件的山峰数量。


解题思路

  1. 识别山峰:遍历数组,找出高度大于相邻位置或位于边界且高于相邻位置的位置。
  2. 预处理体力消耗:对每个位置,预处理从左到右和从右到左的最近地面路径的体力消耗。
  3. 计算最小体力消耗:对于每个山峰,选择左右路径中体力消耗较小的路径。
  4. 统计结果:统计体力消耗不超过给定值的山峰数量。

代码实现

const readline = require('readline');const rl = readline.createInterface({input: process.stdin,output: process.stdout
});let lines = [];
rl.on('line', (line) => {lines.push(line.trim());if (lines.length === 2) {main();rl.close();}
});function main() {const map = lines[0].split(',').map(Number);const energy = parseInt(lines[1], 10);const n = map.length;// 1. 识别所有山峰const peaks = [];for (let i = 0; i < n; i++) {if (map[i] === 0) continue; // 地面不是山峰const leftHigher = i === 0 || map[i] > map[i - 1];const rightHigher = i === n - 1 || map[i] > map[i + 1];if (leftHigher && rightHigher) {peaks.push(i);}}// 2. 预处理左路径的体力消耗const leftCost = new Array(n).fill(Infinity);const leftBackCost = new Array(n).fill(Infinity);let currentGround = -1;let currentCost = 0;let currentBackCost = 0;for (let i = 0; i < n; i++) {if (map[i] === 0) {currentGround = i;currentCost = 0;currentBackCost = 0;leftCost[i] = 0;leftBackCost[i] = 0;} else {if (currentGround !== -1 && i > 0) {const diff = map[i] - map[i - 1];currentCost += diff > 0 ? 2 * diff : -diff;currentBackCost += -diff > 0 ? 2 * (-diff) : diff;}leftCost[i] = currentCost;leftBackCost[i] = currentBackCost;}}// 3. 预处理右路径的体力消耗const rightCost = new Array(n).fill(Infinity);const rightBackCost = new Array(n).fill(Infinity);currentGround = -1;currentCost = 0;currentBackCost = 0;for (let i = n - 1; i >= 0; i--) {if (map[i] === 0) {currentGround = i;currentCost = 0;currentBackCost = 0;rightCost[i] = 0;rightBackCost[i] = 0;} else {if (currentGround !== -1 && i < n - 1) {const diff = map[i] - map[i + 1];currentCost += diff > 0 ? 2 * diff : -diff;currentBackCost += -diff > 0 ? 2 * (-diff) : diff;}rightCost[i] = currentCost;rightBackCost[i] = currentBackCost;}}// 4. 统计符合条件的山峰let count = 0;for (const peak of peaks) {let minCost = Infinity;if (leftCost[peak] + leftBackCost[peak] <= energy) {minCost = Math.min(minCost, leftCost[peak] + leftBackCost[peak]);}if (rightCost[peak] + rightBackCost[peak] <= energy) {minCost = Math.min(minCost, rightCost[peak] + rightBackCost[peak]);}if (minCost <= energy) count++;}console.log(count);
}

代码详细解析

  1. 识别山峰:遍历数组,判断每个位置是否满足山峰条件(高于相邻位置或位于边界)。
  2. 预处理左路径
    • leftCost[i] 记录从左边最近地面到位置 i 的上山体力消耗。
    • leftBackCost[i] 记录从 i 返回到左边地面的下山体力消耗。
  3. 预处理右路径
    • rightCost[i] 记录从右边最近地面到位置 i 的上山体力消耗。
    • rightBackCost[i] 记录从 i 返回到右边地面的下山体力消耗。
  4. 计算最小体力消耗:对于每个山峰,选择左右路径中总消耗较小的路径,判断是否满足体力限制。
  5. 统计结果:统计满足体力限制的山峰数量。

示例测试

示例输入

0,1,4,3,1,0,0,1,2,3,1,2,1,0
13

输出

3

解析:三个山峰(索引2、9、11)的体力消耗均为12,均小于13。


综合分析

  1. 时间复杂度

    • 识别山峰:O(n),遍历数组一次。
    • 预处理路径:两次遍历,O(n)。
    • 统计结果:O(k),k为山峰数量。
    • 总时间复杂度:O(n),高效处理大规模数据。
  2. 空间复杂度

    • 存储预处理数组:O(n),空间复杂度线性。
  3. 优势

    • 预处理优化:通过两次遍历预处理所有路径的体力消耗,避免重复计算。
    • 贪心策略:选择最优路径,确保最小体力消耗。
  4. 适用场景

    • 处理一维数组中的山峰覆盖问题,尤其适合大规模数据。

C++

问题分析

我们需要在给定的地图数组中找到所有山峰,并计算攀登到这些山峰并返回地面的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计符合条件的山峰数量。


解题思路

  1. 识别山峰:遍历数组,找到高度大于相邻位置或位于边界且高于相邻位置的位置。
  2. 预处理最近地面:对每个位置预处理左边和右边最近的地面,并计算路径的总绝对差之和。
  3. 计算体力消耗:利用路径总绝对差之和的3倍,判断是否小于等于体力值。
  4. 统计结果:统计所有满足体力限制的山峰数量。

代码实现

#include <vector>
#include <string>
#include <sstream>
#include <climits>
#include <iostream>using namespace std;int main() {string line;getline(cin, line);istringstream ss(line);vector<int> map;string token;while (getline(ss, token, ',')) {map.push_back(stoi(token));}int energy;cin >> energy;int n = map.size();// 预处理左边最近的地面和总绝对差vector<int> left_ground(n, -1);vector<int> left_sum(n, 0);int current_ground = -1;int current_sum = 0;for (int i = 0; i < n; ++i) {if (map[i] == 0) {current_ground = i;current_sum = 0;} else {if (current_ground != -1 && i > 0) {current_sum += abs(map[i] - map[i - 1]);}}left_ground[i] = current_ground;left_sum[i] = current_sum;}// 预处理右边最近的地面和总绝对差vector<int> right_ground(n, -1);vector<int> right_sum(n, 0);current_ground = -1;current_sum = 0;for (int i = n - 1; i >= 0; --i) {if (map[i] == 0) {current_ground = i;current_sum = 0;} else {if (current_ground != -1 && i < n - 1) {current_sum += abs(map[i] - map[i + 1]);}}right_ground[i] = current_ground;right_sum[i] = current_sum;}// 找出所有山峰vector<int> peaks;for (int i = 0; i < n; ++i) {if (map[i] == 0) continue;bool left_peak = (i == 0) || (map[i] > map[i - 1]);bool right_peak = (i == n - 1) || (map[i] > map[i + 1]);if (left_peak && right_peak) {peaks.push_back(i);}}// 统计满足条件的山峰数量int count = 0;for (int peak : peaks) {int left_cost = (left_ground[peak] != -1) ? left_sum[peak] * 3 : INT_MAX;int right_cost = (right_ground[peak] != -1) ? right_sum[peak] * 3 : INT_MAX;int min_cost = min(left_cost, right_cost);if (min_cost <= energy) {count++;}}cout << count << endl;return 0;
}

代码详细解析

  1. 输入处理:读取输入并解析为整数数组和体力值。
  2. 预处理左边地面
    • left_ground[i] 记录左边最近的地面索引。
    • left_sum[i] 记录从该地面到当前位置的路径总绝对差之和。
  3. 预处理右边地面
    • right_ground[i] 记录右边最近的地面索引。
    • right_sum[i] 记录从当前位置到该地面的路径总绝对差之和。
  4. 识别山峰:遍历数组,判断每个位置是否为山峰(高于相邻位置或位于边界)。
  5. 计算体力消耗:对每个山峰,计算左右路径的最小体力消耗(总绝对差之和 ×3)。
  6. 统计结果:比较体力消耗与给定值,统计符合条件的山峰数量。

示例测试

输入

0,1,4,3,1,0,0,1,2,3,1,2,1,0  
13  

输出

3

解析:三个山峰(索引3、10、12)的体力消耗均为9,均小于13。


综合分析

  1. 时间复杂度

    • 预处理:O(n),两次遍历数组。
    • 识别山峰:O(n),遍历数组一次。
    • 总复杂度:O(n),高效处理大规模数据。
  2. 空间复杂度

    • 存储预处理数组:O(n),空间复杂度线性。
  3. 优势

    • 预处理优化:快速获取路径信息,避免重复计算。
    • 贪心策略:选择最优路径,确保最小体力消耗。
  4. 适用场景

    • 处理一维数组中的山峰覆盖问题,适合大规模数据。

C语言

问题分析

我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并返回地面的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计符合条件的山峰数量。


解题思路

  1. 识别山峰:遍历数组,找到所有符合条件的位置(高度大于相邻位置或位于边界且高于相邻位置)。
  2. 预处理最近地面:对每个位置预处理左边和右边最近的地面,并计算路径的绝对差之和。
  3. 计算体力消耗:每个山峰的体力消耗为路径绝对差之和的3倍,取左右路径的较小值。
  4. 统计结果:比较体力消耗与给定值,统计符合条件的山峰数量。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>int main() {// 读取地图数组char line[1000000];fgets(line, sizeof(line), stdin);line[strcspn(line, "\n")] = '\0'; // 去除换行符int map[100000];int n = 0;char *token = strtok(line, ",");while (token != NULL) {map[n++] = atoi(token);token = strtok(NULL, ",");}// 读取体力值int energy;scanf("%d", &energy);// 预处理左边最近地面和绝对差之和int *left_ground = (int *)malloc(n * sizeof(int));int *left_sum = (int *)malloc(n * sizeof(int));int current_ground = -1;int current_sum = 0;for (int i = 0; i < n; i++) {if (map[i] == 0) {current_ground = i;current_sum = 0;left_ground[i] = i;left_sum[i] = 0;} else {if (current_ground != -1) {if (i > 0) {current_sum += abs(map[i] - map[i - 1]);}left_ground[i] = current_ground;left_sum[i] = current_sum;} else {left_ground[i] = -1;left_sum[i] = 0;}}}// 预处理右边最近地面和绝对差之和int *right_ground = (int *)malloc(n * sizeof(int));int *right_sum = (int *)malloc(n * sizeof(int));current_ground = -1;current_sum = 0;for (int i = n - 1; i >= 0; i--) {if (map[i] == 0) {current_ground = i;current_sum = 0;right_ground[i] = i;right_sum[i] = 0;} else {if (current_ground != -1) {if (i < n - 1) {current_sum += abs(map[i + 1] - map[i]);}right_ground[i] = current_ground;right_sum[i] = current_sum;} else {right_ground[i] = -1;right_sum[i] = 0;}}}// 找出所有山峰int *peaks = (int *)malloc(n * sizeof(int));int peak_count = 0;for (int i = 0; i < n; i++) {if (map[i] == 0) continue;int left_ok = (i == 0) || (map[i] > map[i - 1]);int right_ok = (i == n - 1) || (map[i] > map[i + 1]);if (left_ok && right_ok) {peaks[peak_count++] = i;}}// 计算每个山峰的最小消耗int count = 0;for (int i = 0; i < peak_count; i++) {int peak = peaks[i];int left_cost = (left_ground[peak] != -1) ? left_sum[peak] * 3 : INT_MAX;int right_cost = (right_ground[peak] != -1) ? right_sum[peak] * 3 : INT_MAX;int min_cost = (left_cost < right_cost) ? left_cost : right_cost;if (min_cost <= energy) {count++;}}printf("%d\n", count);// 释放内存free(left_ground);free(left_sum);free(right_ground);free(right_sum);free(peaks);return 0;
}

代码详细解析

  1. 读取输入:将输入的地图数组转换为整数数组,并读取体力值。
  2. 预处理左路径
    • left_ground 数组记录每个位置左边最近的地面索引。
    • left_sum 数组记录从该地面到当前位置的绝对差之和。
  3. 预处理右路径
    • right_ground 数组记录每个位置右边最近的地面索引。
    • right_sum 数组记录从当前位置到该地面的绝对差之和。
  4. 识别山峰:遍历数组,判断每个位置是否满足山峰条件(高于相邻位置或位于边界)。
  5. 计算体力消耗:对每个山峰,取左右路径的体力消耗(绝对差之和 ×3)的较小值。
  6. 统计结果:比较体力消耗与给定值,统计符合条件的山峰数量。

示例测试

输入

0,1,4,3,1,0,0,1,2,3,1,2,1,0
13

输出

3

解析

  • 山峰位置:索引2(4)、9(3)、11(2)。
  • 路径消耗分别为9(右路径)、9(左路径)、6(右路径),均 ≤13。

综合分析

  1. 时间复杂度

    • 预处理:两次遍历数组,时间复杂度 O(n)。
    • 识别山峰:遍历数组一次,时间复杂度 O(n)。
    • 总时间复杂度:O(n),适合处理大规模数据。
  2. 空间复杂度

    • 存储预处理数组和山峰位置:O(n)。
  3. 优势

    • 预处理优化:避免重复计算路径消耗。
    • 贪心策略:选择左右路径中的较小消耗,确保最优解。
  4. 适用场景

    • 处理一维数组中的山峰覆盖问题,尤其适合数据量大的场景。

GO

问题分析

我们需要找到地图数组中的所有山峰,并计算攀登到这些山峰并返回地面的最小体力消耗。若总消耗不超过给定体力值,则该山峰可被攀登。最终统计符合条件的山峰数量。


解题思路

  1. 识别山峰:遍历数组,找出高度大于相邻位置或位于边界且高于相邻位置的位置。
  2. 预处理路径消耗:对每个位置预处理左边和右边最近的地面,并计算路径的总绝对差之和。
  3. 计算体力消耗:利用路径总绝对差之和的3倍,判断是否小于等于体力值。
  4. 统计结果:统计所有满足体力限制的山峰数量。

代码实现

package mainimport ("bufio""fmt""os""strconv""strings"
)func abs(x int) int {if x < 0 {return -x}return x
}func main() {scanner := bufio.NewScanner(os.Stdin)scanner.Scan()line := scanner.Text()mapStr := strings.Split(line, ",")var mapArr []intfor _, s := range mapStr {num, _ := strconv.Atoi(s)mapArr = append(mapArr, num)}scanner.Scan()energy, _ := strconv.Atoi(scanner.Text())n := len(mapArr)// 预处理左边最近地面和累计绝对差leftGround := make([]int, n)leftSum := make([]int, n)currentGround := -1currentSum := 0for i := 0; i < n; i++ {if mapArr[i] == 0 {currentGround = icurrentSum = 0} else {if currentGround != -1 && i > 0 {currentSum += abs(mapArr[i] - mapArr[i-1])}}leftGround[i] = currentGroundleftSum[i] = currentSum}// 预处理右边最近地面和累计绝对差rightGround := make([]int, n)rightSum := make([]int, n)currentGround = -1currentSum = 0for i := n - 1; i >= 0; i-- {if mapArr[i] == 0 {currentGround = icurrentSum = 0} else {if currentGround != -1 && i < n-1 {currentSum += abs(mapArr[i+1] - mapArr[i])}}rightGround[i] = currentGroundrightSum[i] = currentSum}// 找出所有山峰var peaks []intfor i := 0; i < n; i++ {if mapArr[i] == 0 {continue}leftOk := (i == 0) || (mapArr[i] > mapArr[i-1])rightOk := (i == n-1) || (mapArr[i] > mapArr[i+1])if leftOk && rightOk {peaks = append(peaks, i)}}// 统计满足条件的山峰数量count := 0for _, peak := range peaks {leftCost := -1if leftGround[peak] != -1 {leftCost = leftSum[peak] * 3}rightCost := -1if rightGround[peak] != -1 {rightCost = rightSum[peak] * 3}minCost := 0if leftCost == -1 && rightCost == -1 {continue // 无可用路径} else if leftCost == -1 {minCost = rightCost} else if rightCost == -1 {minCost = leftCost} else {if leftCost < rightCost {minCost = leftCost} else {minCost = rightCost}}if minCost <= energy {count++}}fmt.Println(count)
}

代码详细解析

  1. 读取输入:将输入的地图字符串转换为整数数组,并读取体力值。
  2. 预处理左边地面
    • leftGround 记录每个位置左边最近的地面索引。
    • leftSum 记录从该地面到当前位置的路径总绝对差之和。
  3. 预处理右边地面
    • rightGround 记录每个位置右边最近的地面索引。
    • rightSum 记录从当前位置到该地面的路径总绝对差之和。
  4. 识别山峰:遍历数组,判断每个位置是否满足山峰条件。
  5. 计算体力消耗:对每个山峰,取左右路径的体力消耗(总绝对差 ×3)的较小值。
  6. 统计结果:比较体力消耗与给定值,统计符合条件的山峰数量。

示例测试

输入

0,1,4,3,1,0,0,1,2,3,1,2,1,0
13

输出

3

解析

  • 山峰位置:索引2(4)、9(3)、11(2)。
  • 路径消耗分别为9(左路径)、9(右路径)、9(右路径),均 ≤13。

综合分析

  1. 时间复杂度

    • 预处理:两次遍历数组,时间复杂度 O(n)。
    • 识别山峰:遍历数组一次,时间复杂度 O(n)。
    • 总复杂度:O(n),高效处理大规模数据。
  2. 空间复杂度

    • 存储预处理数组和山峰位置:O(n)。
  3. 优势

    • 预处理优化:避免重复计算路径消耗。
    • 贪心策略:选择最优路径,确保最小体力消耗。
  4. 适用场景

    • 处理一维数组中的山峰覆盖问题,尤其适合数据量大的场景。

更多内容:

https://www.kdocs.cn/l/cvk0eoGYucWA

本文发表于【纪元A梦】,关注我,获取更多实用教程/资源!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/79420.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qt硬件与软件通信中 16进制与十进制转化

1. 首先上代码, 这是在qt语言上的操作 截取 01 03 0C 00 00 00 00 00 00 00 0C 00 0C 00 0C 93 70 这串16进制数值进行处理&#xff0c;截取这样一段内容 00 0C 00 0C 00 0C 字节数组转字符串。从bytearray数组转换为string. QString CustomTcpSocket::recieveInfo() {QByteArr…

图形变换算法

一、学习目的 &#xff08;1&#xff09;掌握多面体的存储方法。 &#xff08;2&#xff09;掌握图形的几何变换及投影变换。 &#xff08;3&#xff09;掌握三维形体不同投影方法的投影图的生成原理。 &#xff08;4&#xff09;掌握多面体投影图绘制的编程方法。 二、学…

【JAVAFX】自定义FXML 文件存放的位置以及使用

情况 1&#xff1a;FXML 文件与调用类在同一个包中&#xff08;推荐&#xff09; 假设类 MainApp 的包是 com.example&#xff0c;且 FXML 文件放在 resources/com/example 下&#xff1a; 项目根目录 ├── src │ └── sample │ └── Main.java ├── src/s…

Ubuntu20.04安装企业微信

建议先去企业微信官网看一下有没有linux版本&#xff0c;没有的话在按如下方式安装&#xff0c;不过现在是没有的。 方案 1、使用docker容器 2、使用deepin-wine 3、使用星火应用商店 4. 使用星火包deepin-wine 5、使用ukylin-wine 本人对docker不太熟悉&#xff0c;现…

CSS appearance 属性:掌握UI元素的原生外观

在现代网页设计中&#xff0c;为了达到一致的用户体验&#xff0c;我们有时需要让HTML元素模仿操作系统的默认控件样式。CSS中的appearance属性提供了一种简便的方式来控制这些元素是否以及如何显示其默认外观。本文将详细介绍appearance属性&#xff0c;并通过实际代码示例来展…

十四、C++速通秘籍—函数式编程

目录 上一章节&#xff1a; 一、引言 一、函数式编程基础 三、Lambda 表达式 作用&#xff1a; Lambda 表达式捕获值的方式&#xff1a; 注意&#xff1a; 四、函数对象 函数对象与普通函数对比&#xff1a; 五、函数适配器 1、适配普通函数 2、适配 Lambda 表达式 …

大模型Rag-指令调度

本文主要记录根据用户问题指令&#xff0c;基于大模型做Rag&#xff0c;匹配最相关描述集进行指令调度&#xff0c;可用于匹配后端接口以及展示答案及图表等。 1.指令查询处理逻辑 1.实现思路 指令识别&#xff1a;主要根据用户的问题q计算与指令描述集is [i0, ... , im]和指…

音视频学习 - ffmpeg 编译与调试

编译 环境 macOS Ventrua 13.4 ffmpeg 7.7.1 Visual Studio Code Version: 1.99.0 (Universal) 操作 FFmpeg 下载源码 $ cd ffmpeg-x.y.z $ ./configure nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.If you think configure made a mistake…

golang-常见的语法错误

https://juejin.cn/post/6923477800041054221 看这篇文章 Golang 基础面试高频题详细解析【第一版】来啦&#xff5e; 大叔说码 for-range的坑 func main() { slice : []int{0, 1, 2, 3} m : make(map[int]*int) for key, val : range slice {m[key] &val }for k, v : …

音视频之H.265/HEVC预测编码

H.265/HEVC系列文章&#xff1a; 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 预测编码是视频编码中的核心技术之一。对于视频信号来说&#xff0c;一幅图像内邻近像素之间有着较强的空间相关性,相邻图像之…

基于政务问答的dify接口请求测试

Dify 的智能体后端服务 API 为开发者提供便捷方式&#xff0c;能让前端应用直接调用大语言模型能力。在请求时&#xff0c;需先前往应用左侧导航的 “API Access” 部分&#xff0c;在此可查看文档和管理访问凭据。为保障安全&#xff0c;API 密钥应通过后端调用&#xff0c;避…

VMware Workstation 保姆级 Linux(CentOS) 创建教程(附 iso)

文章目录 一、下载二、创建 一、下载 CentOS-7.9-x86_64-DVD-2009.iso 二、创建 VMware Workstation 保姆级安装教程(附安装包) VMware Workstation 保姆级安装教程(附安装包) VMware Workstation 保姆级安装教程(附安装包)

扩增子分析|基于R语言microeco包进行微生物群落网络分析(network网络、Zi-Pi关键物种和subnet子网络图)

一、引言 microeco包是福建农林大学姚敏杰教授团队开发的扩增子测序集成分析。该包综合了扩增子测序下游分析的多种功能包括群落组成、多样性、网络分析、零模型等等。通过简单的几行代码可实现复杂的分析。因此&#xff0c;microeco包发表以来被学界广泛关注&#xff0c;截止2…

GO语言-数据类型

文章目录 变量定义1. 整数类型2. 浮点类型3. 字符类型4. 布尔类型5. 字符串类型5.1 字符串的本质5.2 常用字符串处理函数(strings包)5.3 修改字符串的方式 6. 数据默认值7. 类型转换 变量定义 代码如下&#xff1a; package mainimport "fmt"var i1 1000 var i2 i…

线性代数 | 知识点整理 Ref 2

注&#xff1a;本文为 “线性代数 | 知识点整理” 相关文章合辑。 因 csdn 篇幅合并超限分篇连载&#xff0c;本篇为 Ref 2。 略作重排&#xff0c;未整理去重。 图片清晰度限于引文原状。 如有内容异常&#xff0c;请看原文。 【数学】线性代数知识点总结 阿巴 Jun 于 2024-…

JavaSE学习(前端初体验)

文章目录 前言一、准备环境二、创建站点&#xff08;创建一个文件夹&#xff09;三、将站点部署到编写器中四、VScode实用小设置五、案例展示 前言 首先了解前端三件套&#xff1a;HTML、CSS、JS HTML&#xff1a;超文本标记语言、框架层、描述数据的&#xff1b; CSS&#xf…

java + spring boot + mybatis 通过时间段进行查询

前端传来的只有日期内容&#xff0c;如&#xff1a;2025-04-17 需要在日期内容的基础上补充时间部分&#xff0c;代码示例&#xff1a; /*** 日志查询&#xff08;分页查询&#xff09;* param recordLogQueryDTO 查询参数对象* return 日志列表*/Overridepublic PageBean<…

解决ubuntu自带火狐浏览器无法播放视频问题

TIPS:一般执行完1 就可以了 首先安装必要的媒体编解码器和插件&#xff1a; # 安装常用媒体编解码器和插件 sudo apt update sudo apt install -y ubuntu-restricted-extras# 安装额外的编解码器 sudo apt install -y ffmpeg# 安装其他视频相关包 sudo apt install -y libavc…

计算机网络:流量控制与可靠传输机制

目录 基本概念 流量控制&#xff1a;别噎着啦&#xff01; 可靠传输&#xff1a;快递必达服务 传输差错&#xff1a;现实中的意外 滑动窗口 基本概念 换句话说&#xff1a;批量发货排队验收 停止-等待协议 SW&#xff08;发1份等1份&#xff09; 超时重传&#xff1a;…

Android组件刷新

Android中刷新View的方法有以下几种&#xff1a; 调用invalidate()方法&#xff0c;该方法会使View树中的所有视图无效或脏&#xff0c;等待下一次绘制时重新绘制。例如&#xff1a; mCustomView.invalidate(); 调用postInvalidate()方法&#xff0c;该方法类似于invalidate()…