【华为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机试,这类固定滑窗问题是常考题型,掌握滑动窗口的思想和实现方式非常重要。

相关推荐
8Qi81 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
youngerwang2 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
KaMeidebaby2 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠3 小时前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc
无限码力4 小时前
阿里算法岗 0530笔试真题 - 多约束条件下的元素匹配统计
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试
lqqjuly4 小时前
MLA — 多头潜在注意力深度解析
深度学习·神经网络·算法
吴可可1234 小时前
SolidWorks草图转三维DWG技巧
算法
redaijufeng5 小时前
C++雾中风景7:闭包
c++·算法·风景
小欣加油5 小时前
leetcode287寻找重复数
数据结构·c++·算法·leetcode
尽兴-6 小时前
2.1 向量基础:Embedding、余弦相似度、欧氏距离、向量检索
算法·embedding·欧氏距离·向量检索·余弦相似度