【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)

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

相关推荐
R.lin11 分钟前
Java 8日期时间API完全指南
java·开发语言·python
哆啦A梦158817 分钟前
商城后台管理系统 03 登录布局
javascript·vue.js·elementui
毕设源码-赖学姐17 分钟前
【开题答辩全过程】以 高校教学质量监控平台为例,包含答辩的问题和答案
java·eclipse
高山上有一只小老虎24 分钟前
翻之矩阵中的行
java·算法
西南胶带の池上桜32 分钟前
1.Pytorch模型应用(线性与非线性预测)
人工智能·pytorch·python
火钳游侠38 分钟前
java单行注释,多行注释,文档注释
java·开发语言
曼巴UE541 分钟前
UE FString, FName ,FText 三者转换,再次学习,官方文档理解
服务器·前端·javascript
code bean1 小时前
【CMake】为什么需要清理 CMake 缓存文件?深入理解 CMake 生成器切换机制
java·spring·缓存
selt7911 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
RestCloud1 小时前
智能制造的底层基建:iPaaS 如何统一 ERP、MES 与 WMS 的数据流
java·wms·erp·数据传输·ipaas·mes·集成平台