news 2026/5/8 9:19:55

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/4/24 8:25:51

‌测试从业者心声:AI工具的真实用户体验‌

技术浪潮下的测试者之困 当生成式AI以每月迭代的速度席卷IT领域时&#xff0c;软件测试行业正经历近十年来最剧烈的工具革命。据Gartner 2025年报告&#xff0c;超过67%的测试团队已引入AI辅助工具&#xff0c;但实际落地效果呈现显著两极分化——部分团队效率提升300%&#x…

作者头像 李华
网站建设 2026/4/30 10:08:56

不用写代码!Open-AutoGLM让普通人玩转AI自动化

不用写代码&#xff01;Open-AutoGLM让普通人玩转AI自动化 1. 引言&#xff1a;当AI成为你的手机助手 你有没有想过&#xff0c;有一天只要动动嘴说一句“帮我打开小红书搜一下周末去哪玩”&#xff0c;手机就会自动执行这一系列操作&#xff1f;不需要你点开App、输入关键词…

作者头像 李华
网站建设 2026/4/25 7:45:36

测试环境生成https自签名证书tls的步骤

# 1. 创建配置文件 cat > gitlab-cert.conf <<EOF [req] default_bits 2048 prompt no default_md sha256 distinguished_name dn req_extensions v3_req [dn] CN gitlab.devops.global-fairy.top O Global Fairy DevOps OU GitLab [v3_req] basicConstraint…

作者头像 李华
网站建设 2026/5/8 3:49:30

tar zxvf swoole.tar.gz的庖丁解牛

tar zxvf swoole.tar.gz 是一条 解压 .tar.gz 格式压缩包 的经典 Linux 命令&#xff0c;常用于源码编译前的准备工作&#xff08;如 Swoole、PHP 扩展等&#xff09;。它看似简单&#xff0c;却涉及 归档、压缩、文件系统 三大核心机制。一、命令结构拆解参数含义作用tarTape …

作者头像 李华
网站建设 2026/5/5 19:39:33

小白必看!用FSMN-VAD快速实现语音识别预处理

小白必看&#xff01;用FSMN-VAD快速实现语音识别预处理 你是不是也遇到过这样的问题&#xff1a;一段几分钟的录音里&#xff0c;真正说话的时间可能只有几十秒&#xff0c;其余全是“嗯”、“啊”、停顿和背景安静&#xff1f;如果要拿这段音频去做语音识别&#xff0c;直接…

作者头像 李华
网站建设 2026/5/5 19:40:55

微信联系作者,技术支持就在身边

微信联系作者&#xff0c;技术支持就在身边 1. 这不是普通抠图工具&#xff0c;而是一次“人对人”的技术交付 你有没有遇到过这样的情况&#xff1a; 下载了一个AI抠图项目&#xff0c;README里写着“pip install -r requirements.txt”&#xff0c;结果卡在PyTorch版本冲突…

作者头像 李华