题目描述
一只贪吃的猴子来到一个果园,发现许多串香蕉排成一行,每串香蕉上有若干根香蕉。每串香蕉的根数由数组 numbers 给出。猴子获取香蕉时,每次都只能从行的开头或者末尾获取,并且只能获取 N 次。求猴子最多能获取多少根香蕉。
输入描述
- 第一行为数组
numbers的长度。 - 第二行为数组
numbers的值,每个数字通过空格分开。 - 第三行输入为
N,表示获取的次数。
输出描述
按照题目要求能获取的最大数值。
测试用例
输入
4
4 2 2 3
2
输出
7
题解
解题思路
这是一个典型的滑动窗口问题。猴子每次只能从数组的开头或末尾获取香蕉,且只能获取 N 次。我们需要找到一种策略,使得猴子获取的香蕉总数最大。
我们可以将问题转化为:在数组的开头和末尾选择一个长度为 N 的窗口,使得窗口内的元素之和最大。
具体步骤如下:
- 计算数组的前
N个元素的和,作为初始的最大值。 - 从数组的末尾开始,依次替换窗口中的元素,计算新的和,并更新最大值。
- 最终得到的最大值即为猴子能获取的最大香蕉数。
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 <iostream>
#include <vector>
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();
复杂度分析
-
时间复杂度:
- 初始窗口计算:(O(N))。
- 滑动窗口计算:(O(N))。
- 总时间复杂度:(O(N))。
-
空间复杂度:
- 只需要常数空间存储变量,空间复杂度为 (O(1))。
测试用例验证
输入
4
4 2 2 3
2
输出
7
解释:
- 初始窗口:
[4, 2],和为 6。 - 滑动窗口:
- 替换为
[2, 3],和为 5。 - 替换为
[4, 3],和为 7。
- 替换为
- 最大和为 7。
总结
通过滑动窗口的方法,我们可以在 (O(N)) 的时间复杂度内解决这个问题。这种方法适用于类似的区间求和问题,能够高效地找到最优解。
华为OD机试:贪吃猴子香蕉获取问题
&spm=1001.2101.3001.5002&articleId=146039921&d=1&t=3&u=e211909300a84edaa57afa16ec808b10)
2557

被折叠的 条评论
为什么被折叠?



