三、239. 滑动窗口最大值--->ali求每k个里面的最大值
3.1 239. 滑动窗口最大值
用的是单调双向队列,该数据结构可以从两端以常数时间压入/弹出元素。
存储双向队列的索引比存储元素更方便,因为两者都能在数组解析中使用。
算法非常直截了当:
处理前 k 个元素,初始化双向队列。
遍历整个数组。在每一步 :
清理双向队列 :
- 只保留当前滑动窗口中有的元素的索引。//pop_front()
- 移除比当前元素小的所有元素,它们不可能是最大的。//pop_back()
将当前元素添加到双向队列中。
将 deque[0] 添加到输出中。//因为是单调队列,队首肯定是最大的
返回输出数组。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;//单调双端队列
vector<int> ans;
int len=0;
for (int i=0;i<nums.size();++i)
{
while (len>0 && (i-dq[0]>=k))
{
dq.pop_front();
--len;
}
while (len>0 && nums[dq[len-1]]<=nums[i])
{
dq.pop_back();
--len;
}
dq.push_back(i);
++len;
if (i>=k-1) ans.push_back(nums[dq[0]]);
}
return ans;
}
};
因为双端队列不光可以双端插入删除,还可以双端访问,所以去掉len改进一下。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;//单调双端队列
vector<int> ans;
for (int i=0;i<nums.size();++i)
{
while (!dq.empty() && (i-dq.front()>=k))
dq.pop_front();
while (!dq.empty() && nums[dq.back()]<=nums[i])
dq.pop_back();
dq.push_back(i);
if (i>=k-1) ans.push_back(nums[dq.front()]);
}
return ans;
}
};
3.2 ali求每k个里面的最小值的最大值
算法:
先把数组排个序,从大到小依次插入,插入的时候判断左右节点是否已经被插入过,如果已经被插入过,合并。合并并且更新集合的数量那就是并查集能做到的事情,记录集合同时维护 集合数量,把last_node_sum+1到new_node_sum的都变成当前值。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
vector<int> parent;
vector<int> rak;
vector<int> cnt;
int findf(int x)
{
return (x==parent[x]? x:parent[x]=findf(parent[x]));
}
void to_union(int a,int b)
{
int f1=findf(a);
int f2=findf(b);
if (rak[f1] > rak[f2])
{
parent[f2] = f1;
cnt[f1]+=cnt[f2];
}
else
{
parent[f1] = f2;
cnt[f2]+=cnt[f1];
if (rak[f1] == rak[f2])
++rak[f2];
}
}
struct node
{
int x,index;
node(int x,int index):x(x),index(index){}
};
bool cmp(node a,node b)
{
return a.x>b.x;
}
int main()
{
int n;
cin>>n;
vector<node> a;
parent.resize(n);
rak.resize(n);
cnt.resize(n);
vector<bool> p(n+10,false);
for (int i=0;i<n;i++)
{
int aa;
cin>>aa;
a.push_back(node(aa,i+1));
parent[i]=i;
rak[i]=1;
cnt[i]=1;
}
sort(a.begin(),a.end(),cmp);
vector<int> ans(n+10);
int now=0;
for (int i=0;i<n;i++)
{
int x=a[i].x,id=a[i].index;
//cout<<x<<' '<<id<<' '<<findf(id-1)<<endl;
if (p[id-1])
to_union(id-2,id-1);
if (p[id+1])
to_union(id,id-1);
p[id]=true;
int last=now;
now=max(now,cnt[findf(id-1)]);
//cout<<last<<' '<<now<<endl;
for (int j=last+1;j<=now;j++)
ans[j]=x;
}
for (int k=1;k<n;++k)
cout<<ans[k]<<' ';
cout<<ans[n]<<endl;
return 0;
}
输入
5
2 5 3 1 2
输出
5 3 2 1 1
四、