滑动窗口的最大值
题目描述
给定一个整数数组 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); } }