LeetCode 题解工作台
将数组和减半的最少操作次数
给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作) 请你返回将 nums 数组和 至少 减少一半的 最少 操作数。 示例 1: 输入: nums = [5,19,8,1] 输出: 3 解…
3
题型
6
代码语言
3
相关题
当前训练重点
中等 · 贪心·invariant
答案摘要
根据题目描述,每一次操作,都会将数组中的一个数减半。要使得数组和至少减少一半的操作次数最少,那么每一次操作都应该选择当前数组中的最大值进行减半。 因此,我们先算出数组要减少的总和 ,然后用一个优先队列(大根堆)维护数组中的所有数,每次从优先队列中取出最大值 ,将其减半,然后将减半后的数重新放入优先队列中,同时更新 ,直到 $s \le 0$ 为止。那么此时的操作次数就是答案。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 贪心·invariant 题型思路
题目描述
给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作)
请你返回将 nums 数组和 至少 减少一半的 最少 操作数。
示例 1:
输入:nums = [5,19,8,1] 输出:3 解释:初始 nums 的和为 5 + 19 + 8 + 1 = 33 。 以下是将数组和减少至少一半的一种方法: 选择数字 19 并减小为 9.5 。 选择数字 9.5 并减小为 4.75 。 选择数字 8 并减小为 4 。 最终数组为 [5, 4.75, 4, 1] ,和为 5 + 4.75 + 4 + 1 = 14.75 。 nums 的和减小了 33 - 14.75 = 18.25 ,减小的部分超过了初始数组和的一半,18.25 >= 33/2 = 16.5 。 我们需要 3 个操作实现题目要求,所以返回 3 。 可以证明,无法通过少于 3 个操作使数组和减少至少一半。
示例 2:
输入:nums = [3,8,20] 输出:3 解释:初始 nums 的和为 3 + 8 + 20 = 31 。 以下是将数组和减少至少一半的一种方法: 选择数字 20 并减小为 10 。 选择数字 10 并减小为 5 。 选择数字 3 并减小为 1.5 。 最终数组为 [1.5, 8, 5] ,和为 1.5 + 8 + 5 = 14.5 。 nums 的和减小了 31 - 14.5 = 16.5 ,减小的部分超过了初始数组和的一半, 16.5 >= 31/2 = 15.5 。 我们需要 3 个操作实现题目要求,所以返回 3 。 可以证明,无法通过少于 3 个操作使数组和减少至少一半。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 107
解题思路
方法一:贪心 + 优先队列(大根堆)
根据题目描述,每一次操作,都会将数组中的一个数减半。要使得数组和至少减少一半的操作次数最少,那么每一次操作都应该选择当前数组中的最大值进行减半。
因此,我们先算出数组要减少的总和 ,然后用一个优先队列(大根堆)维护数组中的所有数,每次从优先队列中取出最大值 ,将其减半,然后将减半后的数重新放入优先队列中,同时更新 ,直到 为止。那么此时的操作次数就是答案。
时间复杂度 ,空间复杂度 。其中 是数组的长度。
class Solution:
def halveArray(self, nums: List[int]) -> int:
s = sum(nums) / 2
pq = []
for x in nums:
heappush(pq, -x)
ans = 0
while s > 0:
t = -heappop(pq) / 2
s -= t
heappush(pq, -t)
ans += 1
return ans
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
The candidate should understand greedy algorithms and their application to real-world problems like this one.
- question_mark
The candidate should be able to justify using a heap for efficiently finding and updating the largest element.
- question_mark
The candidate should highlight the importance of reducing the sum quickly by halving the largest element at each step.
常见陷阱
外企场景- error
Not using a heap may result in inefficient solutions, especially with large arrays.
- error
Forgetting to account for floating-point precision when halving elements multiple times.
- error
Using a non-optimal strategy for halving elements, such as randomly choosing numbers, can lead to more operations.
进阶变体
外企场景- arrow_right_alt
What if the array contains zeros or negative numbers?
- arrow_right_alt
How would the solution change if we were allowed to halve numbers more than once per operation?
- arrow_right_alt
Can this approach be applied to arrays where the sum is not an integer?