Approach #1 Segment Tree [ Accepted ]
Algorithm
It is a RMQ question so we think about the segment tree.We query the Sliding window in O(LogN) .
c++
class Solution {
public:
int n;
vector<int> tree;
void InitTree(vector<int>& nums) {
if(nums.size()>0) {
n=nums.size();
tree.resize(n*2,0);
bulidTree(nums);
}
}
void bulidTree(vector<int>& nums) {
for(int i=n,j=0;i<2*n;i++,j++) {
tree[i]=nums[j];
}
for(int i=n-1;i>0;i--) {
tree[i]=max(tree[i*2],tree[i*2+1]);
}
}
int MaxOfRange(int left, int right) {
left+=n;
right+=n;
int Max=INT_MIN;
while(left<=right) {
if(left%2==1) {
Max=max(Max,tree[left]);
left++;
}
if(right%2==0) {
Max=max(Max,tree[right]);
right--;
}
left/=2;
right/=2;
}
return Max;
}
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
if(nums.size()==0)return ans;
int start=0;
InitTree(nums);
while(start+k-1<nums.size()) {
ans.push_back(MaxOfRange(start,start+k-1));
start++;
}
return ans;
}
};
Complexity Analysis
Time complexity : O(N∗LogN) .
Space complexity : O(N) .
Approach #2 Sparse Table [ Accepted ]
Algorithm
Because it is a RMQ question , so we can do with Sparse table .
c++
class Solution {
public:
void ST(vector<int> & nums){
dp.resize( nums.size() , vector<int>(20,0) );
for( int i = 0; i<nums.size() ; i ++ ){
dp[i][0] = nums[i];
}
for( int j = 1 ; (1<<j) <=nums.size() ; j++ ){
for( int i = 0 ; i +(1<<j)-1< nums.size() ; i ++) {
dp[i][j] = max( dp[i][j-1] , dp[i+(1<<(j-1))][j-1] );
}
}
}
int RMQ(int left , int right ){
int length =(int)(log( ( double )(right - left +1 ) ) /log(2.0) );
return max( dp[left][length] , dp[right - (1<<length) + 1 ][length] );
}
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.size()==0)return ans;
ST(nums);
int start = 0;
while( start + k - 1 < nums.size() ){
ans.push_back( RMQ(start,start+k-1 ) ) ;
start++;
}
return ans ;
}
private:
vector<vector<int>> dp;
vector<int> ans ;
};
Complexity Analysis
Time complexity : O(N∗LogN) .
Space complexity : O(N∗LogN) .
Approach #3 Heap [ Accepted ]
Algorithm
We maintain a heap and refresh the maximum.
c++
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if( nums.size() == 0) {return ans ;}
int i = 0 ;
while(i<k){
qlist.push(nums[i++]);
}
while(1){
ans.push_back( qlist.top() ) ;
if( i == nums.size() ){ break ; }
int start = nums[i-k] , end = nums[i++] ;
qlist.push(end);
hash[start] ++;
while( hash[qlist.top()] ) {
hash[qlist.top()]--;
qlist.pop();
}
}
return ans ;
}
private:
vector<int> ans;
priority_queue<int> qlist;
unordered_map<int,int> hash ;
};
Complexity Analysis
Time complexity : O(N∗LogN) .
Space complexity : O(K) .
Approach #4 Double ended queue [ Accepted ]
Algorithm
We can do this problem with deque
ensure the front is maximum;
save the pos of nums[i];
ensure the front in the sliding windows
save the target to the ans
c++
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> q;
vector<int> ans ;
for( int i = 0 ; i< nums.size() ; i ++) {
//ensure the front is maximum;
while(q.size() && nums[i]>=nums[q.back()]){
q.pop_back();
}
//save the pos of nums[i];
q.push_back(i);
//ensure the front in the sliding windows
if( q.front()== i-k ){
q.pop_front();
}
//save the target to the vector <int> ans
if( i >= k - 1 ){
ans.push_back( nums[q.front()] );
}
}
return ans ;
}
};
Complexity Analysis
Time complexity : O(N) .
Space complexity : O(K) .