📌  相关文章
📜  从所有元素中减去最大值 K 次后找到最终数组(1)

📅  最后修改于: 2023-12-03 15:06:35.554000             🧑  作者: Mango

从所有元素中减去最大值 K 次后找到最终数组

题目描述

给定一个长度为 n 的整数数组 nums,每次操作将会从中选择一个元素并将该元素的值减少 1。

如果符合下列情况之一,则数组 A 就是 锤子数组:

  • 每个元素都是唯一的。
  • 恰好有一个元素的值为 0。

现在,你可以对数组 A 执行最多 K 次操作。请你求出,在最多执行 K 次操作后,数组 A 变成一个 锤子数组 的最小操作次数。

示例

输入:nums = [3, 3, 3, 3, 5, 5, 5, 7, 7, 7], k = 2

输出:2

解释:最优解为将整个数组都减少 2 次,此时数组变为 [1, 1, 1, 1, 3, 3, 3, 5, 5, 5],满足要求。

解题思路

题目可以转换为,将数组中的最大值 n 次减 1,使得数组中不存在值相同的元素或者只有一个值为0的元素。

因此,我们可以先找到数组中的最大值,然后比较 K 和最大值的大小:

  • 如果 K >= 最大值,那么操作后数组中的最大值变成 0,其余元素变成最大值-K。
  • 如果 K < 最大值,那么每次将最大值减 1,同时 K 减 1,直到 K = 0 或者数组变成 锤子数组。

为了方便起见,我们可以先将数组进行排序,这样最大值就在数组的最后一个元素上。

代码实现
def find_min_ops(nums, k):
    nums.sort()
    max_num = nums[-1]
    if k >= max_num:
        return max_num
    else:
        i = len(nums) - 1
        while i > 0 and k > 0:
            diff = min(nums[i] - nums[i-1], k // (len(nums) - i))
            nums[i] -= diff
            k -= diff * (len(nums) - i)
            i -= 1
        return max_num - nums[-1] if k == 0 else max_num - nums[-1] + k // len(nums)
复杂度分析
  • 时间复杂度:$O(nlogn)$,排序复杂度为 $O(nlogn)$,最差情况下的操作次数为 n,因此总时间复杂度为 $O(nlogn)$。
  • 空间复杂度:$O(1)$,只需要常数个变量空间。