Sliding Window——滑动窗口的最大值

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof

题目描述:

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 
解释: 

  滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

提示:

你可以假设k总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

画图分析:

Sliding Window——滑动窗口的最大值_第1张图片

/** 
  * 滑动窗口,
  * Time O(2n) ,n 为 nums 的长度
  * Space O(k),k 窗口大小
  */
class Solution {
     
    public int[] maxSlidingWindow(int[] nums, int k) {
     
        // 如果输入的数组为 null 或者 长度为 0,或者 k 的值为 0,那么返回一个长度为 0 的数组
        if(nums == null || nums.length == 0 || k == 0) return new int[0];
        // 滑动窗口对应的数据结构为双端队列
        Deque<Integer> deque = new LinkedList<>();
        // 创建一个大小为 n = nums.length - k + 1 的数组,作为结果返回
        int[] res = new int[nums.length - k + 1];
        // 当未形成窗口时,主要是对队列对象操作,使得队首元素最大。这就要求滑动的次数为 k 次
        // 1. 当队列为空 2.本次循环的 nums[i] ,可能是最大的,也可能是第二大,第三大,这就要求与队尾的元素进行比较,若大于队尾的元素,就将队尾的元素移除 3.nums[i] 也可能是最小的。
        for(int i = 0; i < k; i++) {
      // 未形成窗口
            while(!deque.isEmpty() && deque.peekLast() < nums[i]) deque.removeLast();
                //将此元素添加至队列。
            deque.addLast(nums[i]);
        }
        //至此,大小为 k 的窗口已形成,可将队首元素,添加到结果数组中。
        res[0] = deque.peekFirst();
        //形成窗口之后,i 开始于 k,终止条件为 < nums.length
        for(int i = k; i < nums.length; i++) {
      // 形成窗口后
            // 如果滑动窗口要删除的那个元素(即窗口的左边界)等于当前队列中最大元素(即队首),意味着队首元素也要随着窗口的滑动而被删除。
            if(deque.peekFirst() == nums[i - k]) deque.removeFirst();
            // 队列不为空(防止空指针异常),并且队列的最后一个元素比 nums[i] 小,移除,保证单调
            while(!deque.isEmpty() && deque.peekLast() < nums[i]) deque.removeLast();
            deque.addLast(nums[i]);
            res[i - k + 1] = deque.peekFirst();
        }
        return res;
    }
}

基础知识:

Java接口参考链接

Java 接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以 interface 来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
接口与类相似点:

  • 一个接口可以有多个方法。
  • 接口文件保存在.java 结尾的文件中,文件名使用接口名。
  • 接口的字节码文件保存在.class 结尾的文件中。
  • 接口相应的字节码文件必须在与包名称相匹配的目录接口中 。

接口与类的区别:

  • 接口不能用实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是被类实现。
  • 接口支持多继承。
Interface Queue<E>
public interface Queue<E> extends Collection<E>
//实现类:LinkedList,PriorityQueue...

Insert: add(e) offer(e)
Remove: remove() poll()
Examine: element() peek()

队列通常但不一定是以FIFO(先进先出)方式排序元素。

Interface Deque <E>
public interface Deque<E> extends Queue<E>
//实现类:LinkedList,...

Insert: addFirst(e) offerFirst(e) addLast(e) offerLast(e)
Remove: removeFirst() pollFirst() removeLast() pollLast()
Examine: getFirst() peekFirst() getLast() peekLast()

你可能感兴趣的:(LeetCode编程训练,数据结构,java,队列)