代码随想录栈与队列——滑动窗口最大值

题目

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

代码随想录栈与队列——滑动窗口最大值_第1张图片

思路

单调队列的思想

单调队列:维护元素单调递增或者单调递减的队列

只维护可能成为最大值的元素
在这里插入图片描述
简单来说,就是,保证队列出口是最大的元素,前面元素比进来的元素小的话就全部挤掉,后面元素比出口元素小的话就保留

比如对于窗口{2,3,5,1,4}中的元素,单调队列只需要维护{5,4}就够了,保证单调队列莉单调递减,此时队列出口元素就是窗口最大元素

java代码如下:

class MyQueue(){//定义单调递减的队列
	Deque<Integer> deque = new LinkedList<>();
	//弹出元素时,比较当前要弹出的元素是否等于队列出口的数值,若果相等则弹出
	//同时判断队列当前是否为空
	void poll (int val){//删除元素操作
		if(!deque.isEmpty() || val == deque.peek()){
			deque.poll();
		}
	}
	    //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素挤掉
    //保证队列元素单调递减
    //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
    void add(int val){
    	while(!deque.Empty() && val > deque.getLast()){//将队列的最后一个元素和新加入的元素val进行对比,加入的元素val比前面的大则弹出前面的元素
    		deque.removeLast();
    	}
    	deque.add(val);
    }
    //队头元素始终为最大元素
    int peek(){
    	return deque.peek();
    }
}

class Solution {
	public int[] maxSlidingWindow(int[] nums,int k){//返回的是记录着滑动窗口每次最大值的数组
		if(nums.length() == 1){
			return nums;
		}
		int len = nums.lenghh() - k + 1;//存放结果数组的大小
		int[] res = new int[len];
		int num = 0;
		//自定义单调队列
		MyQueue myQueue = new MyQueue();
		//先将前k的元素放入队列
		for(iny  i = 0; i < k; i++){
			myQueue.add(nums[i]);
		}
		res[num++] = myQueue.peek();
		for(int  i = k;i< nums.length(); i++){//窗口继续在数组中滑动
			//移除最前面的元素
			myQueue.poll(nums[i-k]);
			//加入最后面的元素
			myQueue.add(nums[i]);
			//记录对应的最大值
			res[num++] = myQueue.peek();
		}
		return res;
	}
}

转载别人的评论:
单调队列真是一种让人感到五味杂陈的数据结构,它的维护过程更是如此…就拿此题来说,队头最大,往队尾方向单调…有机会站在队头的老大永远心狠手辣,当它从队尾杀进去的时候,如果它发现这里面没一个够自己打的,它会毫无人性地屠城,把原先队里的人头全部丢出去,转身建立起自己的政权,野心勃勃地准备开创一个新的王朝…这时候,它的人格竟发生了一百八十度大反转,它变成了一位胸怀宽广的慈父!它热情地请那些新来的“小个子”们入住自己的王国…然而,这些小个子似乎天性都是一样的——嫉妒心强,倘若见到比自己还小的居然更早入住王国,它们会心狠手辣地找一个夜晚把它们通通干掉,好让自己享受更大的“蛋糕”;当然,遇到比自己强大的,它们也没辙,乖乖夹起尾巴做人。像这样的暗杀事件每天都在上演,虽然王国里日益笼罩上白色恐怖,但是好在没有后来者强大到足以干翻国王,江山还算能稳住。直到有一天,闯进来了一位真正厉害的角色,就像当年打江山的国王一样,手段狠辣,野心膨胀,于是又是大屠城…历史总是轮回的。

你可能感兴趣的:(代码随想录,算法,数据结构,leetcode,java)