当前位置: 首页 > news >正文

C++ 随笔:用两个有序集合维护滑动窗口

在需要动态维护滑动窗口内的统计量(如前 K 小值之和或中位数)时,可以使用两个有序集合来实现高效更新。

基本思路:

先确定窗口长度以及在窗口中要维护的元素数量,然后用两个集合 big/small 来区分管理:big 存储当前窗口中符合要求的 K 个元素;small 存储窗口中的其他元素;根据题意决定使用 set 或 multiset,前者不允许重复,后者可以处理重复值。

rebalance

在维护过程中,关键是 rebalance 操作。它负责保持两个集合之间的数量与顺序约束,当 big 的元素数少于目标数量时,就从 small 中取出最高优先级元素转移到 big;若 small 中存在比 big 中优先级更高的元素,则交换两者,使得 big 始终保存窗口中优先级最高的那部分。

auto rebalance=[&](){// 数量少则补while(big.size()<k-1 && !small.empty()){auto it=small.begin();sum+=*it;big.insert(*it);small.erase(it);}// 优先级低则换while(!big.empty() && !small.empty()){auto r = prev(big.end()),l=small.begin();int R=*r, L=*l;if(L<R){sum+=L-R;big.erase(r);big.insert(L);small.erase(l);small.insert(R);}else break;}
};

add/remove

更新时,add 和 remove 分别对应窗口的右移操作。add 用于加入新进入窗口的元素,先插入到 small,再执行一次 rebalance;remove 用于移除滑出窗口的元素,优先从 big 中删除,若不存在再在 small 中删除,之后同样调用 rebalance;根据题意/元素类型看是否添加其他逻辑。

auto add=[&](int k){// 最基础的add,根据题意是否添加其他逻辑small.insert(k);rebalance();
};
auto erase_one=[&](int item){// 删除元素item,优先从 big 中删除if(auto it=big.find(item); it!=big.end()){sum-=item;big.erase(it);}else if(auto it=small.find(item); it!=small.end()){small.erase(it);}
};
auto remove=[&](int k){// 最基础的remove,根据题意是否添加其他逻辑erase_one(k);rebalance();
};

这种两个有序集合维护滑动窗口的技巧,本质上是通过平衡集合间的划分来动态维护一个有序的前缀

问题举例

总体上这类问题的思路就是这样,下面取 LeetCode 中的几个例子:

LeetCode 3321

首先是将原集合中对应的元素删除,之后再将key对应的value操作:加一 or 减一,加一蛮简单的,减一要注意判断边界;如果value归零了,那么就后续不需要在insert进small_set中,否则都需要insert进small_set;最后再通过一个rebalance操作,主要目的将 big_set 补全,数量不足从small中补,比较big当前最小值与small最大值,符合则替换;

struct cmp{bool operator()(const pair<int,int>& a,const pair<int,int>& b)const{if(a.first==b.first)return a.second>b.second;return a.first>b.first;}
};
vector<long long> findXSum(vector<int>& nums, int k, int x){unordered_map<int,int>q;set<pair<int,int>,cmp>big,small;long long sum=0;auto rebalance=[&](){while(big.size()<x && !small.empty()){auto it=small.begin();sum+=1ll*it->first*it->second;big.insert(*it);small.erase(it);}while(!big.empty() && !small.empty()){auto r = prev(big.end()),l=small.begin();if(cmp()(*l,*r)){sum+=1ll*l->first*l->second-1ll*r->first*r->second;auto R=*r,L=*l;big.erase(r);big.insert(L);small.erase(l);small.insert(R);}else break;}};auto erase_one=[&](pair<int,int>item){if(auto it=big.find(item); it!=big.end()){sum-=1ll*it->first*it->second;big.erase(it);}else if(auto it=small.find(item); it!=small.end()){small.erase(it);}};auto add=[&](int k){int v=q[k];erase_one({v,k});q[k]=v+1;small.insert({v+1,k});rebalance();};auto remove=[&](int k){int v=q[k];erase_one({v,k});q[k]=v-1;if(q[k])small.insert({v-1,k});rebalance();};for(int i=0;i<k;i++)add(nums[i]);vector<long long>res{sum};for(int i=k;i<nums.size();i++){remove(nums[i-k]);add(nums[i]);res.push_back(sum);}return res;
}

LeetCode 3013

这样例子要简单一些,就是维护滑动窗口中 k-1 个最小值,可能存在的问题是 滑动窗口的长度和其中要维护的元素个数确定,这点要留心题意,之后的就是固定模板了

long long minimumCost(vector<int>& nums, int k, int x){multiset<int>big,small;long long sum=nums[0];auto rebalance=[&](){while(big.size()<k-1 && !small.empty()){auto it=small.begin();sum+=*it;big.insert(*it);small.erase(it);}while(!big.empty() && !small.empty()){auto r = prev(big.end()),l=small.begin();int R=*r, L=*l;if(L<R){sum+=L-R;big.erase(r);big.insert(L);small.erase(l);small.insert(R);}else break;}};auto erase_one=[&](int item){if(auto it=big.find(item); it!=big.end()){sum-=item;big.erase(it);}else if(auto it=small.find(item); it!=small.end()){small.erase(it);}};auto add=[&](int k){small.insert(k);rebalance();};auto remove=[&](int k){erase_one(k);rebalance();};for(int i=1;i<=x+1;i++)add(nums[i]);long long res=sum;for(int i=x+2;i<nums.size();i++){remove(nums[i-x-1]);add(nums[i]);res=min(res,sum);}return res;
}

后续待补充 中位数维护的两个例子,待我先做完 ✔️

http://www.jsqmd.com/news/31991/

相关文章:

  • 2025年靠谱的台车炉优质厂家推荐榜单
  • 2025年五大能处理诈骗案件的律师推荐
  • ESXI 70 VCenter7.0
  • 后端框架数据对比
  • 2025年靠谱的智能无主灯办公楼系统厂家推荐及选择指南
  • 2025年质量好的地井空调通风软管厂家推荐及选购参考榜
  • 太空舱民宿受欢迎的有哪些?太空舱民宿性价比高的有哪些?
  • 2025年质量好的比例阀厂家推荐及选购指南
  • 2025年质量好的150吨地磅厂家推荐及选购指南
  • 2025年五大靠谱律师团队推荐,介绍陈美娥律师团队手机号
  • 2025年11月脸颊有晒斑产品推荐榜:临床验证淡斑精华实测排名
  • 2025年质量好的客厅壁炉厂家推荐及选择指南
  • 深入解析:Chrome扩展的“秘密通道”:深入解析Native Messaging的安全风险与防御
  • 2025年度太空舱生产厂售后排名:哪家售后好且更值得选
  • 2025年靠谱的阻尼家具滑轨厂家最新推荐权威榜
  • 2025年北京美国本科申请机构权威推荐榜单:美国留学申请/美国本科留学/美国藤校申请源头机构精选
  • CRMEB标准版小票打印的业务逻辑与驱动架构设计
  • 2025年比较好的全拉出阻尼隐藏轨厂家推荐及选购指南
  • 2025年评价高的灯饰灯具PC管优质厂家推荐榜单
  • 2025年口碑好的护手霜厂家实力及用户口碑排行榜
  • 死磕 Elasticsearch 方法论
  • 2025进出线电抗器厂家哪家好?电抗器厂家权威推荐榜单
  • 2025 年碟式离心机制造厂家最新推荐榜单:权威协会测评精选优质企业,为工业生产采购提供专业参考DB440 系列 / DB460 系列 / DB550 系列 / 专业碟式离心机推荐
  • 火热报名中!2025 龙蜥操作系统大会亮点速递
  • yum源安装OpenStackclient
  • 2025年知名的免开槽针式铰链行业内知名厂家排行榜
  • 2025 年最新冷库厂家推荐排行榜:涵盖冷冻 / 装配式 / 酒店单温 / 超低温 / 速冻 / 保鲜冷库及相关设备的优选企业榜单
  • 2025CE认证变压器工厂哪家强?UL认证变压器厂家权威榜单
  • 当下专业甲醛检测服务哪家好TOP10
  • 目前专业甲醛检测服务推荐:2025年权威排名前十