构成特定和需要添加的最少元素

标签: 贪心 数组

难度: Medium

给你一个整数数组 nums ,和两个整数 limitgoal 。数组 nums 有一条重要属性:abs(nums[i]) <= limit

返回使数组元素总和等于 goal 所需要向数组中添加的 最少元素数量 ,添加元素 不应改变 数组中 abs(nums[i]) <= limit 这一属性。

注意,如果 x >= 0 ,那么 abs(x) 等于 x ;否则,等于 -x

 

示例 1:

输入:nums = [1,-1,1], limit = 3, goal = -4
输出:2
解释:可以将 -2 和 -3 添加到数组中,数组的元素总和变为 1 - 1 + 1 - 2 - 3 = -4 。

示例 2:

输入:nums = [1,-10,9,1], limit = 100, goal = 0
输出:1

 

提示:

  • 1 <= nums.length <= 105
  • 1 <= limit <= 106
  • -limit <= nums[i] <= limit
  • -109 <= goal <= 109

Submission

运行时间: 45 ms

内存: 25.9 MB

class Solution:
    def minElements(self, nums: List[int], limit: int, goal: int) -> int:
        diff = goal - sum(nums)
        if diff == 0:
            ans = 0
        elif diff > 0:
            ans = math.ceil(diff/limit)
        else:
            ans = math.ceil(-diff/limit)
        return ans 

Explain

首先计算数组 nums 当前的总和与目标 goal 的差 diff。根据 diff 的正负,我们可以决定添加正数或负数元素以达到目标和。为了最小化添加的元素数量,应尽可能利用 limit 的最大绝对值。因此,我们使用 limit 或 -limit (取决于 diff 的符号)来计算需要添加的元素数量。使用 math.ceil 确保即使不是完全整除也能正确向上取整,确保总和达到 goal。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def minElements(self, nums: List[int], limit: int, goal: int) -> int:
        # 计算目标和与当前和的差
        diff = goal - sum(nums)
        # 如果差为0,无需添加元素
        if diff == 0:
            ans = 0
        elif diff > 0:
            # 差大于0,添加正数
            ans = math.ceil(diff / limit)
        else:
            # 差小于0,添加负数
            ans = math.ceil(-diff / limit)
        return ans # 返回需要添加的元素数量

Explore

在题解中,`diff`是目标和与当前数组和的差值。当`diff`为正时,我们需要添加至少`diff`的和的正值,而当`diff`为负时,我们需要添加至少`-diff`的和的负值。因为可能存在`diff`不能被`limit`整除的情况,使用`math.ceil(diff / limit)`可以确保总是向上取整,即使`diff`除以`limit`有余数时也能保证添加的元素足够,从而确保总和能达到或者超过`goal`。这样可以避免因为向下取整而添加的元素总和不足的问题。

是的,当`diff`接近于0但非零,如`diff`为1或-1时,只需添加一个元素即可。这是因为无论`diff`的绝对值多小,只需至少一个元素即可调整总和以达到`goal`。例如,如果`limit`足够大以覆盖`diff`的绝对值,根据`math.ceil`的计算,`diff / limit`(或`-diff / limit`)将小于1,但向上取整后等于1,表示添加一个相应的元素即可满足要求。

当`limit`为1时,算法无需特别调整。在这种情况下,`limit`为1意味着可以添加任何大小的正数或负数以调整总和。因此,`diff / limit`实际上就是`diff`本身,使用`math.ceil`确保无论`diff`的正负如何,都会添加足够的单位元素以达到`goal`。这种情况下,需要添加的元素数量直接等于`diff`的绝对值。

题解的算法并不依赖于`nums`数组中的值是否满足`abs(nums[i]) <= limit`的条件。算法重点在于计算当前数组总和与目标和的差值`diff`,并根据这个差值来确定需要添加的元素数量。因此,即使`nums`中的元素超过了`limit`,算法仍然有效,因为这不影响`diff`的计算和需要为了达到`goal`而添加的元素数量的确定。