0
点赞
收藏
分享

微信扫一扫

求数组第k小/大的序列和


求数组第 k k k小/大的序列和

弱化版: 非负,求第小。

最小的子序列和是空集

算法流程:

使用优先队列,用二元组 表示当前下标结尾的子序列和

初始加入

每次取出队首。

然后加入

次即为第小的序列和。

时间复杂度:

证明

我们需要证明这样做得到的子序列是不重复、不遗漏、按顺序。

求数组第k小/大的序列和_子序列_12

强化版1: a i a_i ai​ 为整数,求第 k k k大。

显然可以把分成两部分,负数和非负数。

显然第大的和就是

接下来要么减去一个非负数,要么加上一个负数。

这两种情况可以等价为减上一个非负数。然后我们对这些非负数从小到大排序。

然后就转化弱化版的题目的做法,使用优先队列即可。

代码

class Solution {
public:
long long kSum(vector<int> &nums, int k) {
long sum = 0L;
for (int &x : nums)
if (x >= 0) sum += x;
else x = -x;
sort(nums.begin(), nums.end());
priority_queue<pair<long, int>> pq;
pq.emplace(sum, 0);
while (--k) {
auto[sum, i] = pq.top();
pq.pop();
if (i < nums.size()) {
pq.emplace(sum - nums[i], i + 1); // 保留 nums[i-1]
if (i) pq.emplace(sum - nums[i] + nums[i - 1], i + 1); // 不保留 nums[i-1]
}
}
return pq.top().first;
}
};

强化版2: a i a_i ai​ 为整数,求第 k k k小。

类似地。最小的就是负数之和。

接下可以等价为加一个非负数,对这些非负数从小到大排序。

然后转弱化版解法。

代码略。


举报

相关推荐

0 条评论