2702. 使数字变为非正数的最小操作次数 🔒
题目描述
给定一个 下标从0开始 的整数数组 nums,以及两个整数 x 和 y。在每一次操作中,你需要选择一个满足条件 0 <= i < nums.length 的下标 i ,并执行以下操作:
- 将
nums[i]减去x。 - 将除了下标为
i的位置外,其他位置的值都减去y。
返回使得 nums 中的所有整数都 小于等于零 所需的最小操作次数。
示例 1:
输入:nums = [3,4,1,7,6], x = 4, y = 2 输出:3 解释:你需要进行三次操作。其中一种最优操作序列如下: 操作 1: 选择 i = 3。 然后, nums = [1,2,-1,3,4]. 操作 2: 选择 i = 3。 然后, nums = [-1,0,-3,-1,2]. 操作 3: 选择 i = 4。 然后, nums = [-3,-2,-5,-3,-2]. 现在,nums 中的所有数字都是非正数。因此,返回 3。
示例 2:
输入:nums = [1,2,1], x = 2, y = 1 输出:1 解释:我们可以在 i = 1 处执行一次操作,得到 nums = [0,0,0]。所有正数都被移除,因此返回 1。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 1091 <= y < x <= 109
解法
方法一:二分查找
思考
每次可选一个下标减 \(x\),其余位置减 \(y\)。若枚举每次打在哪一个数上,状态随操作次数增长,而 \(nums[i]\) 与操作次数均可到 \(10^9\) 量级,直接模拟不可行。
操作次数 \(t\) 具有单调性:若 \(t\) 次能使全部变为非正,则更多次数亦可。因此对 \(t\) 二分。判定时先假定每个数都享受了 \(t\) 次全局减 \(y\),仍为正的部分必须用「额外减 \(x-y\)」补齐,将这些次数求和并与 \(t\) 比较即可。
我们注意到,如果一个操作次数 \(t\) 能够使得所有的数都小于等于 \(0\),那么对于任意 \(t' > t\),操作次数 \(t'\) 也能够使得所有的数都小于等于 \(0\)。因此我们可以使用二分查找的方法找到最小的操作次数。
我们定义二分查找的左边界 \(l=0\),右边界 \(r=\max(nums)\)。每一次二分查找,我们找到中间值 \(mid=\lfloor\frac{l+r}{2}\rfloor\),然后判断是否存在一种操作方法使得操作次数不超过 \(mid\),使得所有的数都小于等于 \(0\)。如果存在,那么我们就更新右边界 \(r = mid\),否则我们就更新左边界 \(l = mid + 1\)。最终当 \(l=r\) 时,我们就找到了最小的操作次数,返回 \(l\) 即可。
问题的关键在于如何判断是否存在一种操作方法使得操作次数不超过 \(t\),使得所有的数都小于等于 \(0\)。我们可以使用贪心的方法来判断是否存在这样的操作方法。
我们遍历数组中的每一个数 \(v\),如果 \(v \leq t \times y\),那么我们不需要进行任何操作。否则,我们需要的操作次数为 \(\lceil\frac{v - t \times y}{x - y}\rceil\)。我们将所有的操作次数相加,如果小于等于 \(t\),那么就说明存在一种操作方法使得操作次数不超过 \(t\),使得所有的数都小于等于 \(0\)。
时间复杂度 \(O(n \times \log M)\),其中 \(n\) 和 \(M\) 分别是数组的长度和数组中的最大值。空间复杂度 \(O(1)\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
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 29 30 31 32 33 34 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |