滑动窗口在增加元素时,可以在O(1)时间复杂度中,通过将当前最大值和新元素比较而得到更大的元素 但它在删除头元素时,是无法做到直接O(1)复杂度来处理的 因此考虑到用单调队列,可实现O(1)复杂度达到目的,是由双端队列deque改写而来 其特点是,队首元素是最大元素,新加入元素后会依次从队尾向前比较大小,把小的直接删掉,直到队列空或者有更大元素“挡住”,这样能保证最大的一直在队首。这么做的目的是满足程序的需求,程序一直需要直到这个滑动窗口的最大值。 删除单调队列中的某个元素时,会看它在不在队首,不在的话不影响返回最大值,在队首则需要移除,此时的队首最大值就发生改变,原来第二大的现在成为新的最大值
双端队列实现
class Solution {
public:
vector< int > maxSlidingWindow ( vector< int > & nums, int k) {
deque< int > dq;
vector< int > res;
for ( int i = 0 ; i < nums. size ( ) ; i ++ ) {
if ( dq. size ( ) && dq. front ( ) < i - k + 1 ) dq. pop_front ( ) ;
while ( dq. size ( ) && nums[ dq. back ( ) ] <= nums[ i] ) dq. pop_back ( ) ;
dq. push_back ( i) ;
if ( i - k + 1 >= 0 ) res. push_back ( nums[ dq. front ( ) ] ) ;
}
return res;
}
} ;
模拟队列实现
class Solution {
public:
static const int N = 1e5 + 10 ;
int q[ N] ;
int hh, tt = - 1 ;
vector< int > maxSlidingWindow ( vector< int > & nums, int k) {
vector< int > res;
for ( int i = 0 ; i < nums. size ( ) ; i ++ ) {
if ( i - k + 1 > q[ hh] ) hh++ ;
while ( hh <= tt && nums[ q[ tt] ] <= nums[ i] ) tt -- ;
q[ ++ tt] = i;
if ( i + 1 >= k) res. push_back ( nums[ q[ hh] ] ) ;
}
return res;
}
} ;
复杂实现
class MonotonicQueue {
private:
deque< int > data;
public:
void push ( int n) {
while ( ! data. empty ( ) && data. back ( ) < n)
data. pop_back ( ) ;
data. push_back ( n) ;
}
int max ( ) { return data. front ( ) ; }
void pop ( int n) {
if ( ! data. empty ( ) && data. front ( ) == n)
data. pop_front ( ) ;
}
} ;
class Solution {
public:
vector< int > maxSlidingWindow ( vector< int > & nums, int k) {
vector< int > res;
MonotonicQueue window;
for ( int i= 0 ; i< nums. size ( ) ; i++ ) {
if ( i< k- 1 ) {
window. push ( nums[ i] ) ;
} else {
window. push ( nums[ i] ) ;
res. push_back ( window. max ( ) ) ;
window. pop ( nums[ i- k+ 1 ] ) ;
}
}
return res;
}
} ;
void push ( int n) {
while ( data. back ( ) < n && ! data. empty ( ) )
data. pop_back ( ) ;
data. push_back ( n) ;
}
Line 153: Char 16: runtime error: reference binding to misaligned address 0xbebebebebebec0ba for type 'int', which requires 4 byte alignment (stl_deque.h)
0xbebebebebebec0ba: note: pointer points here
<memory cannot be printed>
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_deque.h:162:16
问题就出在while()中两个条件的先后顺序上,显然如果data是空的,就不能执行data.back()这个函数,因此需要首先判断data是否空。故尽管&&表示两个条件并列,但先后顺序还是有讲究