2386. 找出数组的第 K 大和



优先队列 ⟮O(nlogn+klogk)、O(k+logn)⟯
class Solution:
def kSum(self, nums: List[int], k: int) -> int:
n = len(nums)
total = 0
for i in range(n):
if nums[i] > 0:
total += nums[i]
elif nums[i] < 0:
nums[i] = -nums[i]
nums.sort()
ret = 0
pq = [(nums[0], 0)]
for _ in range(2, k + 1):
cur, i = heappop(pq)
ret = cur
if i < n - 1:
heappush(pq, (cur + nums[i + 1], i + 1))
heappush(pq, (cur - nums[i] + nums[i + 1], i + 1))
return total - ret

class Solution {
public:
long long kSum(vector<int>& nums, int k) {
int n = nums.size();
long long total = 0;
for (int i = 0; i < n; ++i){
if (nums[i] > 0){
total += nums[i];
}else if (nums[i] < 0){
nums[i] = -nums[i];
}
}
sort(nums.begin(), nums.end());
long long ret = 0;
priority_queue< pair<long long, int>, vector< pair<long long, int> >, greater<>> pq;
pq.push({nums[0], 0});
for (int j = 2; j <= k; ++j){
auto [cur, i] = pq.top(); pq.pop();
ret = cur;
if (i < n - 1){
pq.push({cur + nums[i + 1], i + 1});
pq.push({cur - nums[i] + nums[i + 1], i + 1});
}
}
return total - ret;
}
};
二分查找 ⟮O(nlogn+klogS)、O(min(n,k))⟯
class Solution:
def kSum(self, nums: List[int], k: int) -> int:
n = len(nums)
total = 0
total2 = 0
for i in range(n):
if nums[i] > 0:
total += nums[i]
elif nums[i] < 0:
nums[i] = -nums[i]
total2 += nums[i]
nums.sort()
cnt = 0
def dfs(i, cur, limit):
nonlocal cnt
if i == n or cnt == k - 1 or cur + nums[i] > limit:
return
cnt += 1
dfs(i + 1, cur + nums[i], limit)
dfs(i + 1, cur, limit)
left = 0
right = total2
while left <= right:
mid = (left + right) // 2
cnt = 0
dfs(0, 0, mid)
if cnt >= k - 1:
right = mid - 1
else:
left = mid + 1
return total - left

class Solution {
public:
long long kSum(vector<int>& nums, int k) {
int n = nums.size();
long long total = 0, total2 = 0;
for (int i = 0; i < n; ++i){
if (nums[i] > 0){
total += nums[i];
}else if (nums[i] < 0){
nums[i] = -nums[i];
}
total2 += nums[i];
}
sort(nums.begin(), nums.end());
function<void(int, long long, long long, int &)> dfs = [&](int i, long long t, long long limit, int &cnt){
if (i == n || cnt == k - 1 || t + nums[i] > limit){
return;
}
cnt++;
dfs(i + 1, t + nums[i], limit, cnt);
dfs(i + 1, t, limit, cnt);
};
long long left = 0, right = total2;
while (left <= right){
long long mid = (left + right) / 2;
int cnt = 0;
dfs(0, 0, mid, cnt);
if (cnt >= k - 1){
right = mid - 1;
}else{
left = mid + 1;
}
}
return total - left;
}
};