【华为OD】阿里巴巴找黄金宝箱

文章目录

【华为OD】阿里巴巴找黄金宝箱

题目描述

一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地,藏宝地有编号从0-N的箱子,每个箱子上面贴有一个数字。阿里巴巴念出一个咒语数字k (k < N),找出连续k个宝箱数字和的最大值,并输出该最大值。

输入输出格式

输入

  • 第一行输入一个数字字串,数字之间使用逗号分隔,例如:2,10,-3,-8,40,5
  • 1 ≤ 字串中数字的个数 ≤ 100000,-10000 ≤ 每个数字 ≤ 10000
  • 第二行输入咒语数字k,例如:4,咒语数字大小小于宝箱的个数

输出

连续k个宝箱数字和的最大值,例如:39

示例

示例一

输入:

复制代码
2,10,-3,-8,40,5
4

输出:

复制代码
39

示例二

输入:

复制代码
8
1

输出:

复制代码
8

解题思路

这是一个典型的滑动窗口问题,需要找到长度为k的连续子数组的最大和。

我们可以用两种方法来解决:

  1. 暴力解法:遍历所有可能的长度为k的子数组,计算每个子数组的和,找出最大值
  2. 滑动窗口优化解法:使用滑动窗口技术,只需要一次遍历即可

解法一:暴力解法

思路

  • 遍历数组中每个可能的起始位置
  • 对于每个起始位置,计算长度为k的子数组和
  • 记录最大值

Java实现

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

public class Solution1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] nums = scanner.nextLine().split(",");
        int k = scanner.nextInt();
        
        int[] arr = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            arr[i] = Integer.parseInt(nums[i]);
        }
        
        int maxSum = Integer.MIN_VALUE;
        
        // 暴力遍历所有长度为k的子数组
        for (int i = 0; i <= arr.length - k; i++) {
            int currentSum = 0;
            for (int j = i; j < i + k; j++) {
                currentSum += arr[j];
            }
            maxSum = Math.max(maxSum, currentSum);
        }
        
        System.out.println(maxSum);
        scanner.close();
    }
}

Python实现

python 复制代码
def find_max_sum_brute_force():
    nums = list(map(int, input().split(',')))
    k = int(input())
    
    max_sum = float('-inf')
    
    # 暴力遍历所有长度为k的子数组
    for i in range(len(nums) - k + 1):
        current_sum = sum(nums[i:i+k])
        max_sum = max(max_sum, current_sum)
    
    print(max_sum)

find_max_sum_brute_force()

C++实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <climits>
#include <algorithm>

using namespace std;

int main() {
    string line;
    getline(cin, line);
    
    vector<int> nums;
    stringstream ss(line);
    string num;
    
    while (getline(ss, num, ',')) {
        nums.push_back(stoi(num));
    }
    
    int k;
    cin >> k;
    
    int maxSum = INT_MIN;
    
    // 暴力遍历所有长度为k的子数组
    for (int i = 0; i <= (int)nums.size() - k; i++) {
        int currentSum = 0;
        for (int j = i; j < i + k; j++) {
            currentSum += nums[j];
        }
        maxSum = max(maxSum, currentSum);
    }
    
    cout << maxSum << endl;
    return 0;
}

解法二:滑动窗口优化解法

思路

  • 首先计算前k个元素的和作为初始窗口
  • 然后滑动窗口:移除窗口左边的元素,添加窗口右边的新元素
  • 在滑动过程中记录最大和

Java实现

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

public class Solution2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] nums = scanner.nextLine().split(",");
        int k = scanner.nextInt();
        
        int[] arr = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            arr[i] = Integer.parseInt(nums[i]);
        }
        
        // 计算第一个窗口的和
        int windowSum = 0;
        for (int i = 0; i < k; i++) {
            windowSum += arr[i];
        }
        
        int maxSum = windowSum;
        
        // 滑动窗口
        for (int i = k; i < arr.length; i++) {
            windowSum = windowSum - arr[i - k] + arr[i];
            maxSum = Math.max(maxSum, windowSum);
        }
        
        System.out.println(maxSum);
        scanner.close();
    }
}

Python实现

python 复制代码
def find_max_sum_sliding_window():
    nums = list(map(int, input().split(',')))
    k = int(input())
    
    # 计算第一个窗口的和
    window_sum = sum(nums[:k])
    max_sum = window_sum
    
    # 滑动窗口
    for i in range(k, len(nums)):
        window_sum = window_sum - nums[i - k] + nums[i]
        max_sum = max(max_sum, window_sum)
    
    print(max_sum)

find_max_sum_sliding_window()

C++实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;

int main() {
    string line;
    getline(cin, line);
    
    vector<int> nums;
    stringstream ss(line);
    string num;
    
    while (getline(ss, num, ',')) {
        nums.push_back(stoi(num));
    }
    
    int k;
    cin >> k;
    
    // 计算第一个窗口的和
    int windowSum = 0;
    for (int i = 0; i < k; i++) {
        windowSum += nums[i];
    }
    
    int maxSum = windowSum;
    
    // 滑动窗口
    for (int i = k; i < (int)nums.size(); i++) {
        windowSum = windowSum - nums[i - k] + nums[i];
        maxSum = max(maxSum, windowSum);
    }
    
    cout << maxSum << endl;
    return 0;
}

复杂度分析

解法一(暴力解法)

  • 时间复杂度:O(n×k),其中n是数组长度
  • 空间复杂度:O(1)

解法二(滑动窗口)

  • 时间复杂度:O(n),其中n是数组长度
  • 空间复杂度:O(1)

总结

滑动窗口是解决这类连续子数组问题的经典方法,相比暴力解法有明显的性能优势。在实际面试中,建议优先考虑滑动窗口解法,它不仅时间复杂度更优,也体现了对算法优化的理解。

对于华为OD机试,这类固定滑窗问题是常考题型,掌握滑动窗口的思想和实现方式非常重要。

相关推荐
是main不是漫1 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法
深圳市快瞳科技有限公司2 小时前
野外鸟类AI识别落地实录:输入适配、结构化输出、去重聚合与置信度分流的工程实践
算法·计算机视觉·鸟类识别·鸟类ai识别·野外鸟类观测·林业调查
专注仿真4 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
小豆庄4 小时前
视频遮罩追踪退场后ID撞号的排查—多目标场景下的失效
opencv·算法·bug·视频·python3.11
Tisfy4 小时前
LeetCode 3882.网格图中最小异或路径:动态规划
算法·leetcode·动态规划
D e re k ZH5 小时前
P5025 [SNOI2017] 炸弹
c++·算法
A boy CDEF girl5 小时前
算法题专栏:优选算法
数据结构·算法·leetcode
没落之王6 小时前
三易五行看宋朝的三界确立
大数据·人工智能·算法
坤坤子吖6 小时前
算法学习——单调队列
开发语言·c++·笔记·学习·算法
Js.Tx8 小时前
【具体数学 Concrete Mathematics】2.1.5 一般性的方法
算法·具体数学