23年用友提前批笔试真题-滑动窗口的最大值

滑动窗口的最大值

题目描述

给定一个整数数组 nums 和一个整数 k,k 表示滑动窗口的大小。你需要找出每个滑动窗口中的最大值与最小值的差,并返回这些差的最大值。

输入描述

数组的长度为 n,1 <= n <= 10000,数组中的每个元素范围为[-10000,10000],滑动窗口大小k的范围为[1,n]。

输出描述

例如,给定一个字符串 "nums = [1,3,-1,-3,5,3,6,7], k = 3",表示一个数组和窗口大小 k。对于该数组中的每个窗口,计算最大值与最小值的差,并返回这些差值中的最大值。

在这个例子中,每个窗口的最大值与最小值的差分别为 [4, 6, 8, 8, 3, 4],因此最终返回的结果是 8。

输入示例
nums = [1,3,-1,-3,5,3,6,7], k = 3
输出示例
8
提示信息

题目输入是一个字符串,需要自己解析为数组和 k 值。

思路:

很典型的滑动窗口最大最小值题目,只需要求出滑动窗口每次移动的最大值与最小值之差的最大值即可。

以求滑动窗口最大值为例:

假设滑动窗口内位于左侧的数的值小于右侧的数的值,那位于左侧的值就完全没用了。因为它的生存时间比右侧的数短,它的值又小,没有与右侧值争夺滑动窗口最大值的可能性。所以我们只需要维护一个非递减队列,即指保存右侧值小于左侧最大值的数,此时队列头的元素就是滑动窗口的最大值。

记住往队列中保存数的时候也要保存数的位置,当它离开滑动窗口时及时把它remove掉。

代码:

import java.lang.*;
import java.util.*;
​
​
class Node{
    private Integer value;//值
​
    private Integer pos;//对应的位置
​
    public Integer getValue() {
        return value;
    }
​
    public Integer getPos() {
        return pos;
    }
​
​
    public Node(Integer value, Integer pos) {
        this.value = value;
        this.pos = pos;
    }
}
public class Main {
​
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        String[] split = s.split(", ",2);
        List<Integer> list = new ArrayList<>();
        int k = Integer.parseInt(split[1].split("=")[1].trim()); // 获取k的值
        String numsString = split[0].split("=")[1].trim(); // 获取nums字符串
        numsString = numsString.substring(1, numsString.length() - 1);
        String[] numsArray = numsString.split(",");
​
        for (String num : numsArray) {
            list.add(Integer.parseInt(num.trim()));
        }
​
        int[] minValue = new int[list.size()-k+1];//维护滑动窗口内最小值
        int[] maxValue = new int[list.size()-k+1];//维护滑动窗口内最大值
​
        List<Node> minList = new LinkedList<>();
        List<Node> maxList = new LinkedList<>();
​
        int ans = 0;
​
        for(int i = 0;i<k;i++){
            while(minList.size()>0&&minList.get(0).getValue()>=list.get(i)){
                minList.remove(0);
            }
            minList.add(new Node(list.get(i),i));
            while(maxList.size()>0&&maxList.get(0).getValue()<=list.get(i)){
                maxList.remove(0);
            }
            maxList.add(new Node(list.get(i),i));
        }
        minValue[0] = minList.get(0).getValue();
        maxValue[0] = maxList.get(0).getValue();
        ans = Math.max(maxValue[0]-minValue[0],ans);
        for(int i = 1;i<list.size()-k+1;i++){
            while(minList.size()>0&&minList.get(0).getPos()<i){
                minList.remove(0);
            }
            while(maxList.size()>0&&maxList.get(0).getPos()<i){
                maxList.remove(0);
            }
            while(minList.size()>0&&minList.get(0).getValue()>=list.get(i+k-1)){
                minList.remove(0);
            }
            minList.add(new Node(list.get(i+k-1),i+k-1));
            while(maxList.size()>0&&maxList.get(0).getValue()<=list.get(i+k-1)){
                maxList.remove(0);
            }
            maxList.add(new Node(list.get(i+k-1),i+k-1));
            minValue[i] = minList.get(0).getValue();
            maxValue[i] = maxList.get(0).getValue();
            ans = Math.max(maxValue[i]-minValue[i],ans);
        }
​
        System.out.println(ans);
​
    }
​
}
​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值