数组滑动窗口中的最大值[单调队列]
来源:互联网 发布:php session有效期 编辑:程序博客网 时间:2024/04/28 15:44
给定大小为N的数组。数组被分为大小为k的子数组,找到每个子数组的最大值。子数组即为滑动窗口。
如果数组为1 2 3 4 5 6,k=2.
子数组为1 2; 2 3; 3 4; 4 5; 5 6
例如:
Input :
arr[] = {1, 2, 3, 1, 4, 5, 2, 3, 6}
k = 3
Output :
3 3 4 5 5 5 6
Input :
arr[] = {8, 5, 10, 7, 9, 4, 15, 12, 90, 13}
k = 4
Output :
10 10 10 15 15 90 90
方法1 直接计算
使用一个两层循环,即可遍历所有的子数组,并找出其中的最大值。
01
#include<stdio.h>
02
03
void
printKMax(
int
arr[],
int
n,
int
k)
04
{
05
int
j, max;
06
07
for
(
int
i = 0; i <= n-k; i++)
08
{
09
max = arr[i];
10
11
for
(j = 1; j < k; j++)
12
{
13
if
(arr[i+j] > max)
14
max = arr[i+j];
15
}
16
printf
(
"%d "
, max);
17
}
18
}
19
20
int
main()
21
{
22
int
arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
23
int
n =
sizeof
(arr)/
sizeof
(arr[0]);
24
int
k = 3;
25
printKMax(arr, n, k);
26
return
0;
27
}
时间复杂度为 O(nk).
方法2 使用平衡二叉树
1) 取出数组中的前K个元素,构建一个平衡二叉树,可以用红黑树或AVL树。
2) 循环 i=0 到 n-k
a) 从二叉树中取出最大的元素,并打印
b) 在二叉树中搜索 arr[i]并删除
c) 将 arr[i+k]插入二叉树
第一步的操作复杂度为O(kLogk),由于循环体每次操作都是lgk,因此总的复杂度为 O(nLogk),总的复杂度为 O(kLogk + (n-k+1)*Logk) ,也就是O(nLogk).
方法3 使用双端队列
创建一个双端队列deque,deque只存储当前的窗口中有用的元素,有用也就是会对未来的选择有影响的元素。插入时保证下面两个性质:
1) 首先,我们保证每次都是队尾插入元素,也就是队首的元素的肯定是距离当前元素最远的。因此每次滑动窗口,只判断队首元素是否超出窗口范围,超出的话则删除。
2) 然后保证deque中的元素是升序的,队尾是最小的元素。由于是从队尾插入,只需要把队尾的元素和当前元素比较即可,不符合条件,则删除队尾元素。
为了判断元素是否超出窗口范围,我们需要存储元素下标。
这种队列,又叫做单调队列,练手题目:POJ 2823
下面是java代码的实现:
01
import
java.util.Deque;
02
import
java.util.LinkedList;
03
04
public
class
MaximumSubArrK {
05
06
static
void
printKMax(
int
arr[],
int
k){
07
Deque<Integer> deque =
new
LinkedList<Integer>();
08
for
(
int
i=
0
; i < arr.length; i++){
09
while
(!deque.isEmpty() && (i-deque.peekFirst()>=k) )
10
deque.pollFirst();
11
while
(!deque.isEmpty() && arr[deque.peekLast()] <= arr[i] )
12
deque.pollLast();
13
deque.addLast(i);
14
if
(i >= k-
1
)
15
System.out.print(arr[ deque.peekFirst() ] +
","
);
16
}
17
System.out.println();
18
}
19
20
public
static
void
main(String[] args) {
21
int
arr[] = {
8
,
5
,
10
,
7
,
9
,
4
,
15
,
12
,
90
,
13
};
22
printKMax(arr ,
4
);
23
24
}
25
}
输出:
1
10
,
10
,
10
,
15
,
15
,
90
,
90
,
时间复杂度为 O(n)。 因为每个元素都最多会被入队列和出队列一次,总的操作次数不会超过2n。
- 数组滑动窗口中的最大值[单调队列]
- 滑动窗口--单调队列
- 单调队列--滑动窗口
- 找出滑动窗口数组中的最大值
- 滑动窗口中的最大值
- POJ2823 滑动窗口 单调队列
- POJ 2823 (从经典滑动窗口最大值问题入门单调队列)
- 滑动窗口(单调队列)讲解_legend
- 【大渣】【单调队列】滑动窗口
- 单调队列——滑动窗口
- poj 2823 滑动窗口 单调队列
- poj2823(滑动窗口,单调队列模板)
- sliding window 滑动窗口(单调队列)
- 【例题&结论】【单调队列(滑动窗口)】NKOJ2152 滑动窗口
- 队列的滑动窗口最大值练习题.
- 多重背包(单调队列(滑动最大值)+二进制方法)
- 生成窗口最大值数组 + 双端队列
- 栈和队列---生成窗口最大值数组
- centos 6.5 连接MySQL 提示:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password:
- Mac MAMP安装Memcached
- 树莓派 常用软件及配置(opencv安装,中文环境设置,VNC配置,截屏)
- js计算年龄
- Android屏幕适配全攻略
- 数组滑动窗口中的最大值[单调队列]
- HDU 1874 畅通工程续(floyed求最短路)
- java方面面试题及个人解答
- hhu 5177 旅游路线 floyd 解题报告
- HDU 4685 强联通分量+网络流
- HDU 2710 Max Factor (素数筛选)
- JSON API免费接口 各种提供JSON格式数据返回服务网站的API接口
- 先行控制技术
- 乱草谈英国实验报告的格式和写法