题目:100232. 超过阈值的最少操作数 II

题目描述

超过阈值的最少操作数 II

给定一个从 0 开始的整数数组 nums 和一个整数 k。你可以进行如下操作:

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

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

目标是使数组中的所有元素都大于或等于 k。请返回实现此目标所需的最少操作次数。

示例

  1. 示例 1:

    • 输入: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,所以我们停止操作。需要的最少操作次数为 2。
  2. 示例 2:

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

提示

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

解决策略

这个问题可以通过贪心算法和最小堆来高效解决。我们每次从数组中选择最小的两个数进行操作,这样可以最快地增加数的总和,更快地达到或超过阈值 k。步骤如下:

  1. 初始化: 将数组转换成最小堆,以便快速找到最小的两个数。

  2. 执行操作: 反复执行以下步骤,直到数组中的所有元素都大于或等于 k

    • 从堆中弹出最小的两个元素 xy
    • 2 * min(x, y) + max(x, y) 添加回堆中。
    • 记录操作次数。
  3. 返回结果: 当所有元素都大于或等于 k 时,返回操作次数。

代码实现

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
import heapq

def min_operations_to_reach_k(nums, k):
# 将数组转换成最小堆
heapq.heapify(nums)
operations = 0

# 当最小的元素小于k时,继续操作
while nums[0] < k:
# 如果数组中只剩一个元素,则无法进行操作
if len(nums) < 2:
return -1 # 返回-1表示无法达到目标

# 弹出最小的两个元素
x = heapq.heappop(nums)
y = heapq.heappop(nums)

# 将新元素插入堆中
heapq.heappush(nums, 2 * min(x, y) + max(x, y))

# 增加操作计数
operations += 1

return operations

# 测试代码
print(min_operations_to_reach_k([2, 11, 10, 1, 3], 10)) # 应为2
print(min_operations_to_reach_k([1, 1, 2, 4, 9], 20)) # 应为4

这段代码使用 Python 的 heapq 模块来有效管理最小堆,确保每次都能快速找到最小的两个数。通过这种方法,我们可以高效地解决这个问题。