滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
思路:就按照题意对数组进行每次k个元素的遍历,保存当前遍历的最大值,直到整个数组遍历完成。
#include<iostream>
using namespace std;
int* maxSlidingWindow(int num[],int k,int n);
int main()
{
int a[]={1,3,-1,-3,5,3,6,7};
int*t=maxSlidingWindow(a,3,8);
for(int i=0;i<6;i++)
cout << t[i] <<" ";
return 0;
}
int* maxSlidingWindow(int num[],int k,int n)
{
int* p=new int[n-k+1];
for(int i=0;i<n-k+1;i++)
{
int m=-100;
for(int j=0;j<k;j++)
{
if(num[i+j]>m)
m=num[i+j];
}
p[i]=m;
}
return p;
}
思路二:思路一的实现比较简单但是性能较差,当数据足够多的时候运行时间特别久,主要原因是进行了很多重复的比较两个相邻的窗口会有大量的重复元素,如果不能利用上一个窗口的数据必然会导致进行无用功。
那么如何利用临近窗口的数据呢?首先我们要确定同一个窗口元素的特征,假设窗口的大小为k,而且窗口是严格按照数组顺序的那么同一个窗口内的元素再数组中对应的下标之差必然是小于k的,那么当出现下标之差等于k的那么必然是该窗口已满且出现了另一个窗口的元素,要剔除。再者我们如何利用临近窗口呢?可以利用一个双向队列,将数组中的元素依次放入队列,若放入的元素不在同一个队列即front()=i-k。说明该窗口已满且第一个元素是上一个窗口的。进行剔除。这就保证数列中总是一个窗口的元素,紧接着如果新加入的元素比之前的n个元素都大就将n个元素全部弹出,把新元素加入,这么做是因为在接下来的窗口最大值只可能是该元素或比该元素更大的。而这样就保证大的元素在前面当遇到小的不用再进行逐个向后比较找最大值因为最大值就是对头,每次比较时候都会有前面的窗口留下的数据做铺垫。
#include<iostream>
#include<deque>
using namespace std;
int* maxSlidingWindow(int num[],int k,int n);
int main()
{
int a[]={1,3,-1,-3,5,3,6,7};
int*t=maxSlidingWindow(a,3,8);
for(int i=0;i<6;i++)
cout << t[i] <<" ";
return 0;
}
int* maxSlidingWindow(int num[],int k,int n)
{
int* p=new int[n-k+1];
deque<int> tem;
for(int i=0;i<n;i++)
{
if(!tem.empty()&&tem.front()==i-k)//弹出多余的元素
tem.pop_front();
while(!tem.empty()&&num[tem.back()]<num[i])//确定新加入元素的位置
tem.pop_back();
tem.push_back(i);
if(i>=k-1)
p[i-k+1]=num[tem.front()];//记录当前窗口最大值
}
return p;
}