【2024年华为OD机试】(B卷,200分)- 跳格子1 (Java & JS & Python&C/C++)

一、问题描述

题目描述

小明和朋友玩跳格子游戏,有 n 个连续格子,每个格子有不同的分数,小朋友可以选择以任意格子起跳,但是不能跳连续的格子,也不能回头跳。

给定一个代表每个格子得分的非负整数数组,计算能够得到的最高分数。

输入描述

给定一个数列,如:1 2 3 1

输出描述

输出能够得到的最高分,如:4

备注

  • 1 ≤ nums.length ≤ 100
  • 0 ≤ nums[i] ≤ 1000

用例

用例 1

输入:

1 2 3 1

输出:

4

说明:

选择跳第一个格子和第三个格子

用例 2

输入:

2 7 9 3 1

输出:

12

说明:
2 + 9 + 1 = 12

题目解析

本题是一个典型的动态规划问题。我们可以使用动态规划来解决这个问题,具体步骤如下:

  1. 定义状态

    • dp[i] 表示跳到第 i 个格子时能够得到的最高分数。
  2. 状态转移方程

    • dp[i] = max(dp[i-1], dp[i-2] + nums[i])
    • dp[i-1] 表示不跳第 i 个格子,保持上一个格子的最高分数。
    • dp[i-2] + nums[i] 表示跳到第 i 个格子,加上第 i 个格子的分数。
  3. 初始化

    • dp[0] = nums[0],跳到第一个格子的最高分数就是第一个格子的分数。
    • dp[1] = max(nums[0], nums[1]),跳到第二个格子的最高分数是前两个格子中较大的一个。
  4. 计算结果

    • 遍历数组,计算每个格子的最高分数。
    • 最终结果是 dp 数组的最后一个元素。

详细步骤

  1. 读取输入

    • 从标准输入读取一个数列,表示每个格子的分数。
  2. 初始化动态规划数组

    • 创建一个 dp 数组,长度与输入数组相同。
    • dp[0] = nums[0]
    • dp[1] = max(nums[0], nums[1])
  3. 计算每个格子的最高分数

    • 从第三个格子开始,遍历数组:
      • dp[i] = max(dp[i-1], dp[i-2] + nums[i])
  4. 输出结果

    • 输出 dp 数组的最后一个元素,即最高分数。

用例解释

用例 1
  • 输入:
    • 1 2 3 1
  • 输出:
    • 4

解释

  • dp[0] = 1
  • dp[1] = max(1, 2) = 2
  • dp[2] = max(2, 1 + 3) = 4
  • dp[3] = max(4, 2 + 1) = 4
  • 最终结果为 4
用例 2
  • 输入:
    • 2 7 9 3 1
  • 输出:
    • 12

解释

  • dp[0] = 2
  • dp[1] = max(2, 7) = 7
  • dp[2] = max(7, 2 + 9) = 11
  • dp[3] = max(11, 7 + 3) = 11
  • dp[4] = max(11, 11 + 1) = 12
  • 最终结果为 12

通过上述步骤,我们可以高效地求出能够得到的最高分数。这种方法的时间复杂度为 O(n),其中 n 是数组的长度。

二、JavaScript算法源码

以下是 JavaScript 代码 的详细中文注释和逻辑讲解:


JavaScript 代码

javascript 复制代码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

// 创建 readline 接口,用于从控制台读取输入
const rl = readline.createInterface({
  input: process.stdin,  // 输入流为标准输入
  output: process.stdout, // 输出流为标准输出
});

// 监听每一行输入
rl.on("line", (line) => {
  // 将输入的字符串按空格分割,并转换为数字数组
  const nums = line.split(" ").map(Number);

  // 调用算法函数并输出结果
  console.log(getResult(nums));
});

// 算法函数
function getResult(nums) {
  const n = nums.length; // 获取数组的长度

  // 创建一个长度为 n 的数组 dp,用于存储动态规划的结果
  const dp = new Array(n).fill(0);

  // 初始化 dp 数组
  if (n >= 1) dp[0] = nums[0]; // 如果数组长度 >= 1,dp[0] 为第一个元素
  if (n >= 2) dp[1] = Math.max(nums[0], nums[1]); // 如果数组长度 >= 2,dp[1] 为前两个元素中的最大值

  // 动态规划递推
  for (let i = 2; i < n; i++) {
    // dp[i] 的值取决于两种情况:
    // 1. 不选择当前元素,则 dp[i] = dp[i - 1]
    // 2. 选择当前元素,则 dp[i] = dp[i - 2] + nums[i]
    // 取两者中的最大值
    dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
  }

  // 返回 dp 数组的最后一个值,即最大和
  return dp[n - 1];
}

代码逻辑讲解

1. 输入处理
  • 使用 readline 模块从控制台读取输入。
  • 输入格式为一行数字,用空格分隔。
  • 将输入字符串按空格分割,并转换为数字数组 nums

2. 算法逻辑
  • 动态规划定义
    • dp[i] 表示从数组 nums 的前 i 个元素中选取不相邻元素的最大和。
  • 初始化
    • 如果数组长度为 1,dp[0] = nums[0]
    • 如果数组长度为 2,dp[1] = Math.max(nums[0], nums[1])
  • 递推公式
    • 对于每个位置 i,有两种选择:
      1. 不选择当前元素,则最大和为 dp[i - 1]
      2. 选择当前元素,则最大和为 dp[i - 2] + nums[i]
    • 取两者中的最大值作为 dp[i]
  • 结果
    • dp[n - 1] 即为从整个数组中选取不相邻元素的最大和。

3. 示例验证
示例 1:
  • 输入:

    1 2 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 1
      • dp[1] = Math.max(1, 2) = 2
    2. 递推:
      • dp[2] = Math.max(dp[1], dp[0] + 3) = Math.max(2, 1 + 3) = 4
      • dp[3] = Math.max(dp[2], dp[1] + 1) = Math.max(4, 2 + 1) = 4
    3. 结果:4
  • 输出:4

示例 2:
  • 输入:

    2 7 9 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 2
      • dp[1] = Math.max(2, 7) = 7
    2. 递推:
      • dp[2] = Math.max(dp[1], dp[0] + 9) = Math.max(7, 2 + 9) = 11
      • dp[3] = Math.max(dp[2], dp[1] + 3) = Math.max(11, 7 + 3) = 11
      • dp[4] = Math.max(dp[3], dp[2] + 1) = Math.max(11, 11 + 1) = 12
    3. 结果:12
  • 输出:12

示例 3:
  • 输入:

    5 5 10 100 10 5
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 5
      • dp[1] = Math.max(5, 5) = 5
    2. 递推:
      • dp[2] = Math.max(dp[1], dp[0] + 10) = Math.max(5, 5 + 10) = 15
      • dp[3] = Math.max(dp[2], dp[1] + 100) = Math.max(15, 5 + 100) = 105
      • dp[4] = Math.max(dp[3], dp[2] + 10) = Math.max(105, 15 + 10) = 105
      • dp[5] = Math.max(dp[4], dp[3] + 5) = Math.max(105, 105 + 5) = 110
    3. 结果:110
  • 输出:110


总结

  • 功能:从数组中选取不相邻的元素,使它们的和最大。
  • 核心逻辑
    1. 使用动态规划记录每一步的最大和。
    2. 通过递推公式计算每个位置的最大和。
    3. 返回最终结果。
  • 适用场景:需要从数组中选取不相邻元素并求最大和的场景。
  • 注意事项
    • 数组中的元素可以为负数,但动态规划的逻辑仍然适用。
    • 时间复杂度为 O(n),空间复杂度为 O(n)

如果有其他问题,欢迎随时提问!

三、Java算法源码

以下是 Java 代码 的详细中文注释和逻辑讲解:


Java 代码

java 复制代码
import java.util.Arrays;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    // 创建 Scanner 对象,用于从控制台读取输入
    Scanner sc = new Scanner(System.in);

    // 读取一行输入,按空格分割成字符串数组,并转换为整数数组
    int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

    // 调用算法函数并输出结果
    System.out.println(getResult(nums));
  }

  // 算法函数
  public static int getResult(int[] nums) {
    int n = nums.length; // 获取数组的长度

    // 创建一个长度为 n 的数组 dp,用于存储动态规划的结果
    int[] dp = new int[n];

    // 初始化 dp 数组
    if (n >= 1) dp[0] = nums[0]; // 如果数组长度 >= 1,dp[0] 为第一个元素
    if (n >= 2) dp[1] = Math.max(nums[0], nums[1]); // 如果数组长度 >= 2,dp[1] 为前两个元素中的最大值

    // 动态规划递推
    for (int i = 2; i < n; i++) {
      // dp[i] 的值取决于两种情况:
      // 1. 不选择当前元素,则 dp[i] = dp[i - 1]
      // 2. 选择当前元素,则 dp[i] = dp[i - 2] + nums[i]
      // 取两者中的最大值
      dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
    }

    // 返回 dp 数组的最后一个值,即最大和
    return dp[n - 1];
  }
}

代码逻辑讲解

1. 输入处理
  • 使用 Scanner 从控制台读取输入。
  • 输入格式为一行数字,用空格分隔。
  • 将输入字符串按空格分割,并转换为整数数组 nums

2. 算法逻辑
  • 动态规划定义
    • dp[i] 表示从数组 nums 的前 i 个元素中选取不相邻元素的最大和。
  • 初始化
    • 如果数组长度为 1,dp[0] = nums[0]
    • 如果数组长度为 2,dp[1] = Math.max(nums[0], nums[1])
  • 递推公式
    • 对于每个位置 i,有两种选择:
      1. 不选择当前元素,则最大和为 dp[i - 1]
      2. 选择当前元素,则最大和为 dp[i - 2] + nums[i]
    • 取两者中的最大值作为 dp[i]
  • 结果
    • dp[n - 1] 即为从整个数组中选取不相邻元素的最大和。

3. 示例验证
示例 1:
  • 输入:

    1 2 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 1
      • dp[1] = Math.max(1, 2) = 2
    2. 递推:
      • dp[2] = Math.max(dp[1], dp[0] + 3) = Math.max(2, 1 + 3) = 4
      • dp[3] = Math.max(dp[2], dp[1] + 1) = Math.max(4, 2 + 1) = 4
    3. 结果:4
  • 输出:4

示例 2:
  • 输入:

    2 7 9 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 2
      • dp[1] = Math.max(2, 7) = 7
    2. 递推:
      • dp[2] = Math.max(dp[1], dp[0] + 9) = Math.max(7, 2 + 9) = 11
      • dp[3] = Math.max(dp[2], dp[1] + 3) = Math.max(11, 7 + 3) = 11
      • dp[4] = Math.max(dp[3], dp[2] + 1) = Math.max(11, 11 + 1) = 12
    3. 结果:12
  • 输出:12

示例 3:
  • 输入:

    5 5 10 100 10 5
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 5
      • dp[1] = Math.max(5, 5) = 5
    2. 递推:
      • dp[2] = Math.max(dp[1], dp[0] + 10) = Math.max(5, 5 + 10) = 15
      • dp[3] = Math.max(dp[2], dp[1] + 100) = Math.max(15, 5 + 100) = 105
      • dp[4] = Math.max(dp[3], dp[2] + 10) = Math.max(105, 15 + 10) = 105
      • dp[5] = Math.max(dp[4], dp[3] + 5) = Math.max(105, 105 + 5) = 110
    3. 结果:110
  • 输出:110


总结

  • 功能:从数组中选取不相邻的元素,使它们的和最大。
  • 核心逻辑
    1. 使用动态规划记录每一步的最大和。
    2. 通过递推公式计算每个位置的最大和。
    3. 返回最终结果。
  • 适用场景:需要从数组中选取不相邻元素并求最大和的场景。
  • 注意事项
    • 数组中的元素可以为负数,但动态规划的逻辑仍然适用。
    • 时间复杂度为 O(n),空间复杂度为 O(n)

如果有其他问题,欢迎随时提问!

四、Python算法源码

以下是 Python 代码 的详细中文注释和逻辑讲解:


Python 代码

python 复制代码
# 输入获取
nums = list(map(int, input().split()))  # 从控制台读取一行输入,按空格分割并转换为整数列表

# 算法入口
def getResult():
    n = len(nums)  # 获取数组的长度

    dp = [0] * n  # 创建一个长度为 n 的数组 dp,用于存储动态规划的结果

    # 初始化 dp 数组
    if n >= 1:
        dp[0] = nums[0]  # 如果数组长度 >= 1,dp[0] 为第一个元素
    if n >= 2:
        dp[1] = max(nums[0], nums[1])  # 如果数组长度 >= 2,dp[1] 为前两个元素中的最大值

    # 动态规划递推
    for i in range(2, n):
        # dp[i] 的值取决于两种情况:
        # 1. 不选择当前元素,则 dp[i] = dp[i - 1]
        # 2. 选择当前元素,则 dp[i] = dp[i - 2] + nums[i]
        # 取两者中的最大值
        dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])

    # 返回 dp 数组的最后一个值,即最大和
    return dp[n - 1]

# 算法调用
print(getResult())  # 调用算法函数并输出结果

代码逻辑讲解

1. 输入处理
  • 使用 input().split() 从控制台读取一行输入,按空格分割成字符串列表。
  • 使用 map(int, ...) 将字符串列表转换为整数列表 nums

2. 算法逻辑
  • 动态规划定义
    • dp[i] 表示从数组 nums 的前 i 个元素中选取不相邻元素的最大和。
  • 初始化
    • 如果数组长度为 1,dp[0] = nums[0]
    • 如果数组长度为 2,dp[1] = max(nums[0], nums[1])
  • 递推公式
    • 对于每个位置 i,有两种选择:
      1. 不选择当前元素,则最大和为 dp[i - 1]
      2. 选择当前元素,则最大和为 dp[i - 2] + nums[i]
    • 取两者中的最大值作为 dp[i]
  • 结果
    • dp[n - 1] 即为从整个数组中选取不相邻元素的最大和。

3. 示例验证
示例 1:
  • 输入:

    1 2 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 1
      • dp[1] = max(1, 2) = 2
    2. 递推:
      • dp[2] = max(dp[1], dp[0] + 3) = max(2, 1 + 3) = 4
      • dp[3] = max(dp[2], dp[1] + 1) = max(4, 2 + 1) = 4
    3. 结果:4
  • 输出:4

示例 2:
  • 输入:

    2 7 9 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 2
      • dp[1] = max(2, 7) = 7
    2. 递推:
      • dp[2] = max(dp[1], dp[0] + 9) = max(7, 2 + 9) = 11
      • dp[3] = max(dp[2], dp[1] + 3) = max(11, 7 + 3) = 11
      • dp[4] = max(dp[3], dp[2] + 1) = max(11, 11 + 1) = 12
    3. 结果:12
  • 输出:12

示例 3:
  • 输入:

    5 5 10 100 10 5
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 5
      • dp[1] = max(5, 5) = 5
    2. 递推:
      • dp[2] = max(dp[1], dp[0] + 10) = max(5, 5 + 10) = 15
      • dp[3] = max(dp[2], dp[1] + 100) = max(15, 5 + 100) = 105
      • dp[4] = max(dp[3], dp[2] + 10) = max(105, 15 + 10) = 105
      • dp[5] = max(dp[4], dp[3] + 5) = max(105, 105 + 5) = 110
    3. 结果:110
  • 输出:110


总结

  • 功能:从数组中选取不相邻的元素,使它们的和最大。
  • 核心逻辑
    1. 使用动态规划记录每一步的最大和。
    2. 通过递推公式计算每个位置的最大和。
    3. 返回最终结果。
  • 适用场景:需要从数组中选取不相邻元素并求最大和的场景。
  • 注意事项
    • 数组中的元素可以为负数,但动态规划的逻辑仍然适用。
    • 时间复杂度为 O(n),空间复杂度为 O(n)

如果有其他问题,欢迎随时提问!

五、C/C++算法源码:

以下是 C 语言代码C++ 代码 的详细中文注释和逻辑讲解:


C 语言代码

c 复制代码
#include <stdio.h>

#define MAX_SIZE 100  // 定义数组的最大长度

#define MAX(a, b) a > b ? a : b  // 定义宏,用于求两个数的最大值

// 算法函数
int getResult(int* nums, int nums_size);

int main() {
    int nums[MAX_SIZE];  // 定义数组,用于存储输入的数字
    int nums_size = 0;   // 记录数组的实际长度

    // 从控制台读取输入,直到遇到换行符
    while (scanf("%d", &nums[nums_size++])) {
        if (getchar() != ' ') break;  // 如果下一个字符不是空格,则结束输入
    }

    // 调用算法函数并输出结果
    printf("%d\n", getResult(nums, nums_size));

    return 0;
}

// 算法实现
int getResult(int* nums, int nums_size) {
    int dp[MAX_SIZE] = {0};  // 定义 dp 数组,用于存储动态规划的结果

    // 初始化 dp 数组
    if (nums_size >= 1) {
        dp[0] = nums[0];  // 如果数组长度 >= 1,dp[0] 为第一个元素
    }
    if (nums_size >= 2) {
        dp[1] = MAX(nums[0], nums[1]);  // 如果数组长度 >= 2,dp[1] 为前两个元素中的最大值
    }

    // 动态规划递推
    for (int i = 2; i < nums_size; i++) {
        // dp[i] 的值取决于两种情况:
        // 1. 不选择当前元素,则 dp[i] = dp[i - 1]
        // 2. 选择当前元素,则 dp[i] = dp[i - 2] + nums[i]
        // 取两者中的最大值
        dp[i] = MAX(dp[i - 1], dp[i - 2] + nums[i]);
    }

    // 返回 dp 数组的最后一个值,即最大和
    return dp[nums_size - 1];
}

C++ 代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>  // 包含 max 函数

using namespace std;

// 算法函数
int getResult(vector<int>& nums);

int main() {
    vector<int> nums;  // 定义动态数组,用于存储输入的数字
    int num;

    // 从控制台读取输入,直到遇到换行符
    while (cin >> num) {
        nums.push_back(num);  // 将输入的数字添加到数组中
        if (cin.get() != ' ') break;  // 如果下一个字符不是空格,则结束输入
    }

    // 调用算法函数并输出结果
    cout << getResult(nums) << endl;

    return 0;
}

// 算法实现
int getResult(vector<int>& nums) {
    int n = nums.size();  // 获取数组的长度

    vector<int> dp(n, 0);  // 定义 dp 数组,初始化为 0

    // 初始化 dp 数组
    if (n >= 1) {
        dp[0] = nums[0];  // 如果数组长度 >= 1,dp[0] 为第一个元素
    }
    if (n >= 2) {
        dp[1] = max(nums[0], nums[1]);  // 如果数组长度 >= 2,dp[1] 为前两个元素中的最大值
    }

    // 动态规划递推
    for (int i = 2; i < n; i++) {
        // dp[i] 的值取决于两种情况:
        // 1. 不选择当前元素,则 dp[i] = dp[i - 1]
        // 2. 选择当前元素,则 dp[i] = dp[i - 2] + nums[i]
        // 取两者中的最大值
        dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);
    }

    // 返回 dp 数组的最后一个值,即最大和
    return dp[n - 1];
}

代码逻辑讲解

1. 输入处理
  • C 语言
    • 使用 scanf 从控制台读取输入,直到遇到换行符。
    • 将输入的数字存储到数组 nums 中,并记录数组的实际长度 nums_size
  • C++
    • 使用 cin 从控制台读取输入,直到遇到换行符。
    • 将输入的数字存储到动态数组 nums 中。

2. 算法逻辑
  • 动态规划定义
    • dp[i] 表示从数组 nums 的前 i 个元素中选取不相邻元素的最大和。
  • 初始化
    • 如果数组长度为 1,dp[0] = nums[0]
    • 如果数组长度为 2,dp[1] = max(nums[0], nums[1])
  • 递推公式
    • 对于每个位置 i,有两种选择:
      1. 不选择当前元素,则最大和为 dp[i - 1]
      2. 选择当前元素,则最大和为 dp[i - 2] + nums[i]
    • 取两者中的最大值作为 dp[i]
  • 结果
    • dp[n - 1] 即为从整个数组中选取不相邻元素的最大和。

3. 示例验证
示例 1:
  • 输入:

    1 2 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 1
      • dp[1] = max(1, 2) = 2
    2. 递推:
      • dp[2] = max(dp[1], dp[0] + 3) = max(2, 1 + 3) = 4
      • dp[3] = max(dp[2], dp[1] + 1) = max(4, 2 + 1) = 4
    3. 结果:4
  • 输出:4

示例 2:
  • 输入:

    2 7 9 3 1
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 2
      • dp[1] = max(2, 7) = 7
    2. 递推:
      • dp[2] = max(dp[1], dp[0] + 9) = max(7, 2 + 9) = 11
      • dp[3] = max(dp[2], dp[1] + 3) = max(11, 7 + 3) = 11
      • dp[4] = max(dp[3], dp[2] + 1) = max(11, 11 + 1) = 12
    3. 结果:12
  • 输出:12

示例 3:
  • 输入:

    5 5 10 100 10 5
    
  • 处理过程:

    1. 初始化:
      • dp[0] = 5
      • dp[1] = max(5, 5) = 5
    2. 递推:
      • dp[2] = max(dp[1], dp[0] + 10) = max(5, 5 + 10) = 15
      • dp[3] = max(dp[2], dp[1] + 100) = max(15, 5 + 100) = 105
      • dp[4] = max(dp[3], dp[2] + 10) = max(105, 15 + 10) = 105
      • dp[5] = max(dp[4], dp[3] + 5) = max(105, 105 + 5) = 110
    3. 结果:110
  • 输出:110


总结

  • 功能:从数组中选取不相邻的元素,使它们的和最大。
  • 核心逻辑
    1. 使用动态规划记录每一步的最大和。
    2. 通过递推公式计算每个位置的最大和。
    3. 返回最终结果。
  • 适用场景:需要从数组中选取不相邻元素并求最大和的场景。
  • 注意事项
    • 数组中的元素可以为负数,但动态规划的逻辑仍然适用。
    • 时间复杂度为 O(n),空间复杂度为 O(n)

如果有其他问题,欢迎随时提问!

相关推荐
然后就去远行吧几秒前
小程序组件 —— 31 事件系统 - 事件绑定和事件对象
前端·javascript·小程序
夕阳_醉了5 分钟前
如何在JS里进行深拷贝
开发语言·javascript·ecmascript
日暮温柔1 小时前
实现nacos配置修改后无需重启服务--使用@RefreshScope注解
java
疯狂的沙粒2 小时前
对React的高阶组件的理解?应用场景?
前端·javascript·react.js·前端框架
星云code2 小时前
【HM-React】08. Layout模块
javascript·react.js·ecmascript
武昌库里写JAVA2 小时前
React方向:react中5种Dom的操作方式
java·开发语言·spring boot·学习·课程设计
ThetaarSofVenice2 小时前
一个个顺序挨着来 - 责任链模式(Chain of Responsibility Pattern)
java·设计模式·责任链模式
数据小小爬虫3 小时前
利用Java爬虫获取义乌购店铺所有商品列表:技术探索与实践
java·开发语言·爬虫
WeeJot嵌入式3 小时前
【C语言】标准IO
c语言·后端
互联网-小阿宇3 小时前
【HTML+CSS+JS+VUE】web前端教程-31-css3新特性
前端·javascript·css