LeetCode 题解工作台

将数组和减半的最少操作次数

给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作) 请你返回将 nums 数组和 至少 减少一半的 最少 操作数。 示例 1: 输入: nums = [5,19,8,1] 输出: 3 解…

category

3

题型

code_blocks

6

代码语言

hub

3

相关题

当前训练重点

中等 · 贪心·invariant

bolt

答案摘要

根据题目描述,每一次操作,都会将数组中的一个数减半。要使得数组和至少减少一半的操作次数最少,那么每一次操作都应该选择当前数组中的最大值进行减半。 因此,我们先算出数组要减少的总和 ,然后用一个优先队列(大根堆)维护数组中的所有数,每次从优先队列中取出最大值 ,将其减半,然后将减半后的数重新放入优先队列中,同时更新 ,直到 $s \le 0$ 为止。那么此时的操作次数就是答案。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 贪心·invariant 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个正整数数组 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 <= 105
  • 1 <= nums[i] <= 107
lightbulb

解题思路

方法一:贪心 + 优先队列(大根堆)

根据题目描述,每一次操作,都会将数组中的一个数减半。要使得数组和至少减少一半的操作次数最少,那么每一次操作都应该选择当前数组中的最大值进行减半。

因此,我们先算出数组要减少的总和 ss,然后用一个优先队列(大根堆)维护数组中的所有数,每次从优先队列中取出最大值 tt,将其减半,然后将减半后的数重新放入优先队列中,同时更新 ss,直到 s0s \le 0 为止。那么此时的操作次数就是答案。

时间复杂度 O(n×logn)O(n \times \log n),空间复杂度 O(n)O(n)。其中 nn 是数组的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • 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.

warning

常见陷阱

外企场景
  • 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.

swap_horiz

进阶变体

外企场景
  • 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?

help

常见问题

外企场景

将数组和减半的最少操作次数题解:贪心·invariant | LeetCode #2208 中等