数组中恰好K个非连续元素最小和算法实现疑问
数组中选取恰好K个非连续元素的最小和问题解析
问题描述
给定长度为N的整数数组costs和整数K,需返回数组中恰好K个非相邻元素的最小和。约束条件:
- 1 <= N <= 1000000
- 1 <= K <= int(N/2)
- 1 <= costs[i] <= 1e11(1<=i<=N)
直观的二维DP解法(dp[i][j]表示前i个元素选j个非相邻元素的最小和)时间复杂度为O(nk),对于n=1e6的规模完全无法满足性能要求,因此需要O(k log n)的高效算法。
问题分析:算法失效原因
你参考的CodeforcesO(k log n)算法核心是反悔贪心+优先队列,但失效案例(N=5,K=3,cost=[2,1,5,4,7])得到错误结果,本质是对算法的核心逻辑理解偏差——尤其是选中元素后对相邻元素的处理、双向链表维护、虚拟元素的意义这三点没有正确实现。
该案例中唯一合法的选法是选取索引0、2、4的元素(和为14),但错误的算法实现会错误地选中索引1、3的元素后,试图再选一个已被禁用的元素,导致结果错误。
正确的O(k log n)算法实现思路
算法核心是利用最小堆(优先队列)维护当前可选的最小代价元素,结合双向链表跟踪元素的真实邻居,通过虚拟元素实现"反悔"操作,具体步骤如下:
初始化
- 维护三个数组:
prev[]:记录每个元素当前的左邻居索引,初始prev[i] = i-1,prev[0] = -1next[]:记录每个元素当前的右邻居索引,初始next[i] = i+1,next[N-1] = -1deleted[]:标记元素是否已被删除(无法选中或作为邻居),初始全为false
- 将所有元素的
(costs[i], i)存入最小堆(按元素值升序排序) - 初始化总和
total = 0,选取次数count = 0
核心循环
当count < K时:
- 弹出堆顶元素,直到找到未被删除的元素
(val, curr) - 将
val加入total,count +=1 - 找到
curr的真实邻居:left = prev[curr],right = next[curr] - 创建虚拟元素:计算虚拟值
virtual_val = 0- 若
left != -1,virtual_val += costs[left],标记deleted[left] = true - 若
right != -1,virtual_val += costs[right],标记deleted[right] = true virtual_val -= costs[curr]
- 若
- 更新
costs[curr] = virtual_val(此时curr代表"反悔选当前元素,转而选左右邻居"的代价) - 维护双向链表:
- 若
left != -1,prev[curr] = prev[left];否则prev[curr] = -1 - 若
right != -1,next[curr] = next[right];否则next[curr] = -1 - 若
prev[curr] != -1,next[prev[curr]] = curr - 若
next[curr] != -1,prev[next[curr]] = curr
- 若
- 将
(virtual_val, curr)重新存入堆中
算法逻辑说明
选中元素curr后,其左右邻居无法再被选中。虚拟元素的意义是记录"反悔操作"的代价:如果后续发现选左右邻居比选curr更优,可以通过选中这个虚拟元素,将总和调整为total - costs[curr] + costs[left] + costs[right],等价于放弃curr、转而选left和right,同时保证非相邻的约束。
失效案例验证
以N=5,K=3,cost=[2,1,5,4,7]为例:
- 第一次选堆顶元素
(1,1),total=1。处理邻居0和2,虚拟值为2+5-1=6,标记0、2为删除,更新链表后将(6,1)放回堆。 - 第二次选堆顶元素
(4,3),total=5。处理邻居1和4,虚拟值为6+7-4=9,标记1、4为删除,更新链表后将(9,3)放回堆。 - 第三次选堆顶元素
(9,3),total=5+9=14,达到K=3,返回结果14,与预期一致。
实现注意事项
- 堆中会存在已被标记为删除的元素,每次取堆顶时必须检查
deleted状态,弹出无效元素直到找到有效元素。 - 双向链表的维护必须准确,否则会导致邻居查找错误,破坏算法逻辑。
- 由于
N可达1e6,需使用高效的优先队列实现(如C++的priority_queue,或Python的heapq,但Python需注意堆的大小控制)。
内容的提问来源于stack exchange,提问作者user27916452
相关产品推荐
相关产品推荐

