力扣第125场双周赛

前言

双周赛地址:https://leetcode.cn/contest/biweekly-contest-125/

超过阈值的最少操作数 I

本文由 简悦 SimpRead 转码, 原文地址 leetcode.cn

  1. 超过阈值的最少操作数 I - 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。

一次操作中,你可以删除 nums 中的最小元素。

你需要使数组中的所有元素都大于或等于 k ,请你返回需要的 最少 操作次数。

示例 1:

1
2
3
4
5
6
7
8
9
输入:nums = [2,11,10,1,3], k = 10
输出:3
解释:第一次操作后,nums 变为 [2, 11, 10, 3]
第二次操作后,nums 变为 [11, 10, 3]
第三次操作后,nums 变为 [11, 10]
此时,数组中的所有元素都大于等于 10 ,所以我们停止操作。
使数组中所有元素都大于等于 10 需要的最少操作次数为 3 。


示例 2:

1
2
3
4
输入:nums = [1,1,2,4,9], k = 1
输出:0
解释:数组中的所有元素都大于等于 1 ,所以不需要对 nums 做任何操作。

示例 3:

1
2
3
4
5
输入:nums = [1,1,2,4,9], k = 9
输出:4
解释:nums 中只有一个元素大于等于 9 ,所以需要执行 4 次操作。


提示:

  • 1 <= nums.length <= 50
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109
  • 输入保证至少有一个满足 nums[i] >= k 的下标 i 存在。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <vector>
#include <algorithm>

int minOperations(std::vector<int>& nums, int k) {
// 首先对数组进行排序
std::sort(nums.begin(), nums.end());

// 初始化操作次数
int count = 0;

// 从数组最小端开始去除元素
for (int i = 0; i < nums.size(); i++) {
if (nums[i] < k) {
// 计算操作次数
count++;
} else {
// 已经满足条件,跳出循环
break;
}
}

// 返回最小操作次数
return count;
}

int main() {
// 示例测试
std::vector<int> nums1 = {2, 11, 10, 1, 3};
int k1 = 10;
std::cout << "Example 1: " << minOperations(nums1, k1) << std::endl; // 应该输出 3

std::vector<int> nums2 = {1, 1, 2, 4, 9};
int k2 = 1;
std::cout << "Example 2: " << minOperations(nums2, k2) << std::endl; // 应该输出 0

std::vector<int> nums3 = {1, 1, 2, 4, 9};
int k3 = 9;
std::cout << "Example 3: " << minOperations(nums3, k3) << std::endl; // 应该输出 4

return 0;
}

程序中先将数组进行排序,然后从第一个元素遍历,每次移除小于k的元素。这样我们实际上可以通过求得被移除掉的元素数量,来计算最小的操作次数。复杂度是O(nlogn),因为我们使用了排序。这是问题的基本解法,如果数组非常大,还有更多优化的空间。

超过阈值的最少操作数 II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
int minOperations(vector<int>& nums, int k) {
// 使用优先队列(最小堆)来存储所有元素,便于获取最小的两个数
std::priority_queue<long long, std::vector<long long>, std::greater<long long>> pq(nums.begin(), nums.end());

long long ops = 0; // 初始化操作次数

// 只有当堆中至少有两个元素时,才能进行操作
while (pq.size() > 1 && pq.top() < k) {
long long x = pq.top(); pq.pop(); // 堆中最小的元素
long long y = pq.top(); pq.pop(); // 堆中第二小的元素

// 进行合并操作,然后将结果放回堆中
pq.push(x * 2 + y);

// 操作次数加一
ops++;
}

// 检查是否所有元素都大于或等于 k
// 如果堆顶元素小于 k,则无法通过操作使所有元素大于或等于 k
if (pq.top() < k) {
return -1; // 返回-1表示无法完成任务
}
return ops;
}
};

本文由 简悦 SimpRead 转码, 原文地址 leetcode.cn

  1. 超过阈值的最少操作数 II - 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。

一次操作中,你将执行:

  • 选择 nums 中最小的两个整数 x 和 y 。
  • 将 x 和 y 从 nums 中删除。
  • 将 min(x, y) * 2 + max(x, y) 添加到数组中的任意位置。

注意,只有当 nums 至少包含两个元素时,你才可以执行以上操作。

你需要使数组中的所有元素都大于或等于 k ,请你返回需要的 最少 操作次数。

示例 1:

1
2
3
4
5
6
7
8
输入:nums = [2,11,10,1,3], k = 10
输出:2
解释:第一次操作中,我们删除元素 1 2 ,然后添加 1 * 2 + 2 到 nums 中,nums 变为 [4, 11, 10, 3] 。
第二次操作中,我们删除元素 3 4 ,然后添加 3 * 2 + 4 到 nums 中,nums 变为 [10, 11, 10] 。
此时,数组中的所有元素都大于等于 10 ,所以我们停止操作。
使数组中所有元素都大于等于 10 需要的最少操作次数为 2


示例 2:

1
2
3
4
5
6
7
8
9
输入:nums = [1,1,2,4,9], k = 20
输出:4
解释:第一次操作后,nums 变为 [2, 4, 9, 3]
第二次操作后,nums 变为 [7, 4, 9]
第三次操作后,nums 变为 [15, 9]
第四次操作后,nums 变为 [33]
此时,数组中的所有元素都大于等于 20 ,所以我们停止操作。
使数组中所有元素都大于等于 20 需要的最少操作次数为 4 。

提示:

  • 2 <= nums.length <= 2 * 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109
  • 输入保证答案一定存在,也就是说一定存在一个操作序列使数组中所有元素都大于等于 k






贡献者

函数的基本逻辑是:

  1. 检查数组中是否至少有两个元素,如果不是,则无法执行操作。
  2. 如果数组中所有元素都已经大于或等于k,那么就不需要执行操作。
  3. 如果需要执行操作,就对数组进行排序,并删除最小的两个元素x和y,将min(x,y)*2+max(x,y)添加回数组中。
  4. 重复上述步骤,直到所有元素都大于或等于k。
作者

JIeJaitt

发布于

2024-03-04

更新于

2024-03-04

许可协议

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×