【华为OD机试真题 Java语言】1、滑动窗口最大值 | 机试真题+思路参考+代码解析

本文提供了一道华为在线开发者(OD)机试真题的解析,涉及使用Java解决滑动窗口最大值的问题。文章详细介绍了题意、输入输出格式,给出了多个样例,并详细阐述了解题思路,包括如何初始化窗口和、计算最大窗口和等步骤。最后,还提供了问题解答和代码参考。
摘要由CSDN通过智能技术生成


🍂个人博客首页: KJ.JK
 
🍂专栏介绍: 华为OD机试真题汇总,定期更新华为OD各个时间阶段的机试真题,每日定时更新,本专栏将使用Java语言进行更新解答,包含真题,思路分析,代码参考,欢迎大家订阅学习


一、题目


🎃题目描述

有一个N个整数的数组,和一个长度为M的窗口,窗口从数组内的第一个数开始滑动直到窗口不能滑动为止,
 
每次窗口滑动产生一个窗口和(窗口内所有数的和),求窗口滑动产生的所有窗口和的最大值


🎃输入输出

输入
第一行输入一个正整数N,表示整数个数。(0<N<100000)
第二行输入N个整数,整数的取值范围为[-100,100]。
第三行输入一个正整数M,M代表窗口的大小,M<=100000,且M<=N。
 
输出
窗口滑动产生所有窗口和的最大值


🎃样例1

输入
6
12 10 20 30 15 23
3


输出
68

说明

窗口长度为3,窗口滑动产生的窗口和分别为10+20+30=6020+30+15=6530+15+23=6815+23+12=50,

所以窗口滑动产生的所有窗口和的最大值为68

这里上面的原题是这样的描述,但感觉好像不是这样,所以重新模拟了一下窗口,说明:

滑动窗口和应该是不跨越数组边界的连续子数组的和。

所以,滑动窗口应该是这样的:

  • 第一个窗口:12 + 10 + 20 = 42
  • 第二个窗口:10 + 20 + 30 = 60
  • 第三个窗口:20 + 30 + 15 = 65
  • 第四个窗口:30 + 15 + 23 = 68

在数组内部连续地移动。


🎃样例2

输入
5
1 2 3 4 5
3



输出
12

🎃样例3

输入
7
-1 -2 -3 -4 -5 6 7
2




输出
13

🎃样例4

输入
8
-5 4 -3 9 -1 0 5 -2
4




输出
13

🎃样例5

输入
6
0 2 0 0 0 1
2




输出
2

🎃样例6

输入
5
100 -100 100 -100 100
3




输出
100

🎃样例7

输入
4
1 3 5 7
2



输出
12

🎃样例8

输入
6
-5 -4 -3 -2 -1 0
3




输出
-3

🎃样例9

输入
7
1 2 3 4 5 6 7
4



输出
22

🎃样例10

输入
5
-2 3 -4 5 -6
2




输出
1

🎃样例11

输入
6
1 -1 2 -2 3 -3
3




输出
3

二、思路参考


1、首先,从输入中获取数组的长度 N,并创建一个大小为 N 的整数数组 arr

2、使用循环,将输入的 N 个整数依次存储到数组 arr 中

3、获取窗口大小 M

4、初始化一个变量 windowSum 为 0,用于存储当前窗口内元素的和

5、使用一个循环,计算初始窗口大小为 M 的子数组的和,并将结果存储在 windowSum 变量中

6、将 windowSum 的值赋给变量 maxSum,作为初始的最大窗口和

7、使用另一个循环,从第 M 个元素开始,不断移动滑动窗口。在每次迭代中,更新窗口和 windowSum,通过减去窗口最左端的元素并加上窗口最右端的元素。然后,使用 Math.max 方法将 windowSum 和 maxSum 的较大值更新到 maxSum 变量中

8、循环结束后,maxSum 中存储的就是整个数组中连续子数组的和的最大值

9、最后,输出 maxSum 的值,即最大窗口和


三、问题解疑

❓Q1:按照题目的要求 15+23+12这个窗口是不能出现的吧
 
⭕A1:滑动窗口和应该是不跨越数组边界的连续子数组的和。
 
所以,滑动窗口应该是这样的:

  • 第一个窗口:12 + 10 + 20 = 42
  • 第二个窗口:10 + 20 + 30 = 60
  • 第三个窗口:20 + 30 + 15 = 65
  • 第四个窗口:30 + 15 + 23 = 68
     
    应该是原题目的案例描述不对,这里进行补充说明

四、代码参考

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();  // 输入数组的长度
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            arr[i] = scanner.nextInt();  // 输入数组元素
        }
        int M = scanner.nextInt();  // 窗口大小

        int windowSum = 0;  // 窗口内元素的和
        for (int i = 0; i < M; i++) {
            windowSum += arr[i];  // 计算初始窗口和
        }
        int maxSum = windowSum;  // 初始最大窗口和

        for (int i = M; i < N; i++) {
            windowSum = windowSum - arr[i - M] + arr[i];  // 更新窗口和
            maxSum = Math.max(maxSum, windowSum);  // 更新最大窗口和
        }

        System.out.println(maxSum);  // 输出结果
    }
}


作者:KJ.JK

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KJ.JK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值