news 2026/2/18 8:51:39

leetcode 3507(小根堆+懒删除)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
leetcode 3507(小根堆+懒删除)

3507: 移除最小数对使数组有序Ⅰ

思路1:小数据范围 暴力模拟

class Solution { public: int minimumPairRemoval(vector<int>& nums) { int n=nums.size(),ans=0,ap=0; bool flag=false; while(!flag){ flag=true; for(int i=1;i<n;i++){ if(nums[i]<nums[i-1]){ flag=false; break; } } if(flag==true && ap==0) return 0; ap++; if(!flag){ int min=INT_MAX,index=0; for(int i=1;i<n;i++){ int sum=nums[i]+nums[i-1]; if(sum<min){ min=sum; index=i-1; } } nums[index]=min; nums.erase(nums.begin()+index+1); n--; ans++; } else return ans; } return ans; } };

为了快速模拟题目的操作,我们需要维护三种信息:

  1. 把相邻元素和 s,以及相邻元素中的左边元素的下标i,组成一个 pair (s,i)。我们需要添加 pair、删除 pair 以及查询这些 pair 的最小值(双关键字比较),这可以用有序集合,或者懒删除堆。
  2. 维护剩余下标。我们需要查询每个下标 i 左侧最近剩余下标,以及右侧最近剩余下标。这可以用有序集合,或者两个并查集,或者双向链表。(用数组模拟)
  3. 在相邻元素中,满足「左边元素大于右边元素」(递减)的个数,记作 dec。

不断模拟操作,直到 dec=0。

题目说「用它们的和替换这对元素」,设操作的这对元素的下标为 i 和 nxt,操作相当于把 nums[i] 增加 nums[nxt],然后删除 nums[nxt]。

在这个过程中,dec 如何变化?

设操作的这对元素的下标为 i 和 nxt,i 左侧最近剩余下标为 pre,nxt 右侧最近剩余下标为 nxt2​。操作会影响 nums[i] 和 nums[nxt],也会影响周边相邻元素的大小关系。所以每次操作,我们需要重新考察 4 个元素值的大小关系,其下标从左到右为 pre,i,nxt,nxt2。

  1. 删除 nums[nxt]。如果删除前 nums[i]>nums[nxt],把 dec 减一。
  2. 如果删除前 nums[pre]>nums[i],把 dec 减一。如果删除后 nums[pre]>s,把 dec 加一。这里 s 表示操作的这对元素之和,也就是新的 nums[i] 的值。
  3. 如果删除前 nums[nxt]>nums[nxt2],把 dec 减一。删除后 i 和 nxt2相邻,如果删除后 s>nums[nxt2],把 dec 加一。

上述过程中,同时维护(添加删除)新旧相邻元素和以及下标。

思路2:懒删除堆+数组模拟双向链表

  • 用最小堆(懒删除堆)代替维护 pair 的有序集合。
  • 双向链表代替维护下标的有序集合。进一步地,可以用两个数组模拟双向链表的 prev 指针和 next 指针。
  • 如果堆顶下标 i 被删除,或者 i 右边下标 nxt 被删除,或者堆顶元素和不等于 nums[i]+nums[nxt],则弹出堆顶。
vector<int> left(n+1),right(n); ranges::iota(left,-1); //值域:-1, 0, 1, 2, ..., n-1 ranges::iota(right,1); //值域:1, 2, 3, ..., n

vector<long long> a(nums.begin(),nums.end());

right[pq.top().second]>=n || pq.top().first!=a[pq.top().second]+a[right[pq.top().second]]

这一长串判断是“懒删除”的经典写法,出现在堆/优先队列里,用来跳过那些已经失效(被合并过或移动过)的元素。

int l=left[nxt],r=right[nxt]; right[l]=r; //模拟双向链表的删除操作 left[r]=l; right[nxt]=n; //满足懒删除条件

这三行就是在用双向链表的方式把节点nxt从当前链里“逻辑删除”,而并不真的挪动数组元素。链表里再也遍历不到nxt,相当于把它“跳过”了;后续代码只要看到right[i] >= n(懒删除条件)就知道i已被删。

class Solution { public: int minimumPairRemoval(vector<int>& nums) { int n=nums.size(); //小根堆(相邻元素和,左边那个数的下标) priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<>> pq; int dec=0; //递减的相邻对的个数 for(int i=0;i<n-1;i++){ int x=nums[i],y=nums[i+1]; if(x>y) dec++; pq.emplace(x+y,i); } //每个下标的左右最近的未删除下标(映射) vector<int> left(n+1),right(n); ranges::iota(left,-1); //值域:-1, 0, 1, 2, ..., n-1 ranges::iota(right,1); //值域:1, 2, 3, ..., n vector<long long> a(nums.begin(),nums.end()); int ans=0; while(dec){ ans++; //如果堆顶数据与实际数据不符,说明堆顶数据是之前本应删除,但没有删除的数据(懒删除) while(right[pq.top().second]>=n || pq.top().first!=a[pq.top().second]+a[right[pq.top().second]]){ pq.pop(); } auto[s,i]=pq.top(); pq.pop(); //删除相邻元素和最小的一对 //(当前元素,下一个数) int nxt=right[i]; dec-=a[i]>a[nxt]; //旧数据 //(前一个数,当前元素) int pre=left[i]; if(pre>=0){ dec-=a[pre]>a[i]; //旧数据 dec+=a[pre]>s; //新数据 pq.emplace(a[pre]+s,pre); } //(下一个数,下下一个数) int nxt2=right[nxt]; if(nxt2<n){ dec-=a[nxt]>a[nxt2]; //旧数据 dec+=s>a[nxt2]; //新数据(当前元素,下下一个数) pq.emplace(s+a[nxt2],i);//nxt被删除了 } a[i]=s; //删除 nxt int l=left[nxt],r=right[nxt]; right[l]=r; //模拟双向链表的删除操作 left[r]=l; right[nxt]=n; //满足懒删除条件 } return ans; } };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/17 6:44:16

Qwen3-0.6B效果展示:一句话生成完整代码

Qwen3-0.6B效果展示&#xff1a;一句话生成完整代码 Qwen3-0.6B是阿里巴巴于2025年4月开源的新一代轻量级大语言模型&#xff0c;参数量仅0.6B却具备远超同规模模型的代码生成能力。它不是“能写点代码”的玩具模型&#xff0c;而是真正能在开发一线帮上忙的实用工具——输入一…

作者头像 李华
网站建设 2026/2/7 15:14:15

3个高效NLP工具推荐:BERT中文填空镜像开箱即用

3个高效NLP工具推荐&#xff1a;BERT中文填空镜像开箱即用 1. BERT 智能语义填空服务&#xff1a;让AI补全你的中文句子 你有没有遇到过这样的场景&#xff1f;写文案时卡在一个词上&#xff0c;翻遍词典也找不到最贴切的表达&#xff1b;或者读古诗时看到一句“疑是地[MASK]…

作者头像 李华
网站建设 2026/2/13 23:23:44

保存路径在哪?fft npainting lama输出文件位置说明

保存路径在哪&#xff1f;FFT NPainting Lama输出文件位置说明 在使用FFT NPainting Lama图像修复工具时&#xff0c;很多用户都会遇到一个看似简单却很关键的问题&#xff1a;修复完成的图片到底保存在哪里了&#xff1f; 为什么我在Web界面看到“已保存”提示&#xff0c;却…

作者头像 李华
网站建设 2026/2/16 20:41:44

Sambert情感转换精度提升:微调训练部署前置准备

Sambert情感转换精度提升&#xff1a;微调训练部署前置准备 1. Sambert 多情感中文语音合成——开箱即用版 你是不是也遇到过这样的问题&#xff1a;想做一个带情绪的语音助手&#xff0c;或者为短视频配上富有感情的旁白&#xff0c;但市面上大多数语音合成工具都“面无表情…

作者头像 李华
网站建设 2026/2/14 19:38:59

DeepSeek-R1-Distill-Qwen-1.5B API封装:FastAPI集成教程

DeepSeek-R1-Distill-Qwen-1.5B API封装&#xff1a;FastAPI集成教程 你是不是也遇到过这样的问题&#xff1a;手头有个性能不错的轻量级大模型&#xff0c;比如 DeepSeek-R1-Distill-Qwen-1.5B&#xff0c;它数学推理强、代码生成稳、逻辑清晰&#xff0c;但每次调用都要写一…

作者头像 李华
网站建设 2026/2/17 8:53:54

Speech Seaco Paraformer系统信息查看指南:模型状态监控实战

Speech Seaco Paraformer系统信息查看指南&#xff1a;模型状态监控实战 1. 引言&#xff1a;为什么需要监控模型运行状态&#xff1f; 你有没有遇到过这种情况&#xff1a;语音识别突然变慢、批量处理卡住不动、或者Web界面打不开&#xff1f;这些问题背后&#xff0c;往往是…

作者头像 李华