滑动窗口、尺取法学习笔记

滑动窗口解决什么问题?

1. 需要输出或比较的结果在原数据结构中是连续排列的;

2. 每次窗口滑动时,只需观察窗口两端元素的变化,无论窗口多长,每次只操作两个头尾元素,当用到的窗口比较长时,可以显著减少操作次数;

3. 窗口内元素的整体性比较强,窗口滑动可以只通过操作头尾两个位置的变化实现,但对比结果时往往要用到窗口中所有元素。

 

滑动窗口、尺取法关系?

尺取法就是双指针(two points)嘛。而滑动窗口也要用到二个指针,所以滑动窗口是一种特殊的尺取法。

 

经典例题:

leetcode 239. 滑动窗口最大值

题意:

在一个数组中找长度为k的子序列 中的最大值,如下图所示:

  滑动窗口的位置                最大值
  ---------------                        -----
[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的子序列,说明窗口的大小是固定的,且为k。

找每个窗口中的最大值,我们可以遍历窗口中的所有值,从而找到最大值,此时,时间复杂度为O(n * m)

用单调双端队列找最大值可以使时间复杂度变为O(n)。

下面用的单调双端队列 是单调递减的。那么队列的第一个元素即为最大值,而且,队列前面的数 一定 比队列后面的数放入时间早。

class Solution {
public:
	vector<int> maxSlidingWindow(vector<int>& nums, int k) {
		vector<int> res;
		if (nums.size() <= 0 || k < 1 || k > nums.size()){
			return res;
		}

		deque<int> list;//创建双端队列
		for (int i = 0; i < nums.size(); i++){ //i表示窗口的结尾下标
			while (list.size() != 0 && nums[*(list.end() - 1)] <= nums[i]){
				list.pop_back();
			}//while
			list.push_back(i);

			if (*list.begin() == i - k){
				list.pop_front();
			}//if

			if (i >= k - 1){ //i 要到 k - 1位置处才是一个完整的窗口
				res.push_back(nums[*list.begin()]);
			}//if
		}//for
		return res;
	}
};<
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值