华为OD机试-贪吃的猴子(2024 E卷 200分)

题目描述

一只贪吃的猴子来到一个果园,发现许多串香蕉排成一行,每串香蕉上有若干根香蕉。每串香蕉的根数由数组 numbers 给出。猴子获取香蕉时,每次都只能从行的开头或者末尾获取,并且只能获取 N 次。求猴子最多能获取多少根香蕉。

输入描述

  1. 第一行为数组 numbers 的长度。
  2. 第二行为数组 numbers 的值,每个数字通过空格分开。
  3. 第三行输入为 N,表示获取的次数。

输出描述

按照题目要求能获取的最大数值。

测试用例

输入

4
4 2 2 3
2

输出

7

题解

解题思路

这是一个典型的滑动窗口问题。猴子每次只能从数组的开头或末尾获取香蕉,且只能获取 N 次。我们需要找到一种策略,使得猴子获取的香蕉总数最大。

我们可以将问题转化为:在数组的开头和末尾选择一个长度为 N 的窗口,使得窗口内的元素之和最大。

具体步骤如下:

  1. 计算数组的前 N 个元素的和,作为初始的最大值。
  2. 从数组的末尾开始,依次替换窗口中的元素,计算新的和,并更新最大值。
  3. 最终得到的最大值即为猴子能获取的最大香蕉数。

Java 实现

import java.util.Scanner;

public class MaxBananas {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取数组长度
        int length = scanner.nextInt();
        int[] numbers = new int[length];
        
        // 读取数组元素
        for (int i = 0; i < length; i++) {
            numbers[i] = scanner.nextInt();
        }
        
        // 读取获取次数 N
        int N = scanner.nextInt();
        
        // 计算最大香蕉数
        int maxSum = 0;
        int currentSum = 0;
        
        // 初始窗口:前 N 个元素
        for (int i = 0; i < N; i++) {
            currentSum += numbers[i];
        }
        maxSum = currentSum;
        
        // 滑动窗口:从末尾开始替换
        for (int i = 0; i < N; i++) {
            currentSum = currentSum - numbers[N - 1 - i] + numbers[length - 1 - i];
            if (currentSum > maxSum) {
                maxSum = currentSum;
            }
        }
        
        // 输出结果
        System.out.println(maxSum);
    }
}

Python 实现

def max_bananas():
    # 读取数组长度
    length = int(input())
    # 读取数组元素
    numbers = list(map(int, input().split()))
    # 读取获取次数 N
    N = int(input())
    
    # 初始窗口:前 N 个元素
    current_sum = sum(numbers[:N])
    max_sum = current_sum
    
    # 滑动窗口:从末尾开始替换
    for i in range(N):
        current_sum = current_sum - numbers[N - 1 - i] + numbers[-(i + 1)]
        if current_sum > max_sum:
            max_sum = current_sum
    
    # 输出结果
    print(max_sum)

# 调用函数
max_bananas()

C++ 实现

#include 
#include 
using namespace std;

int main() {
    // 读取数组长度
    int length;
    cin >> length;
    vector<int> numbers(length);
    
    // 读取数组元素
    for (int i = 0; i < length; i++) {
        cin >> numbers[i];
    }
    
    // 读取获取次数 N
    int N;
    cin >> N;
    
    // 初始窗口:前 N 个元素
    int currentSum = 0;
    for (int i = 0; i < N; i++) {
        currentSum += numbers[i];
    }
    int maxSum = currentSum;
    
    // 滑动窗口:从末尾开始替换
    for (int i = 0; i < N; i++) {
        currentSum = currentSum - numbers[N - 1 - i] + numbers[length - 1 - i];
        if (currentSum > maxSum) {
            maxSum = currentSum;
        }
    }
    
    // 输出结果
    cout << maxSum << endl;
    
    return 0;
}

JavaScript 实现

function maxBananas() {
    const readline = require('readline');
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    let length, numbers, N;

    rl.question('', (len) => {
        length = parseInt(len);
        rl.question('', (nums) => {
            numbers = nums.split(' ').map(Number);
            rl.question('', (n) => {
                N = parseInt(n);

                // 初始窗口:前 N 个元素
                let currentSum = numbers.slice(0, N).reduce((a, b) => a + b, 0);
                let maxSum = currentSum;

                // 滑动窗口:从末尾开始替换
                for (let i = 0; i < N; i++) {
                    currentSum = currentSum - numbers[N - 1 - i] + numbers[numbers.length - 1 - i];
                    if (currentSum > maxSum) {
                        maxSum = currentSum;
                    }
                }

                // 输出结果
                console.log(maxSum);
                rl.close();
            });
        });
    });
}

// 调用函数
maxBananas();

复杂度分析

  1. 时间复杂度

    • 初始窗口计算:(O(N))。
    • 滑动窗口计算:(O(N))。
    • 总时间复杂度:(O(N))。
  2. 空间复杂度

    • 只需要常数空间存储变量,空间复杂度为 (O(1))。

测试用例验证

输入

4
4 2 2 3
2

输出

7

解释

  • 初始窗口:[4, 2],和为 6。
  • 滑动窗口:
    • 替换为 [2, 3],和为 5。
    • 替换为 [4, 3],和为 7。
  • 最大和为 7。

总结

通过滑动窗口的方法,我们可以在 (O(N)) 的时间复杂度内解决这个问题。这种方法适用于类似的区间求和问题,能够高效地找到最优解。

你可能感兴趣的:(华为OD机试,华为OD,机试,算法,Java,Python,C++,JavaScript)