题解:将数组所有元素变为相同的最小操作次数
思路解析
题目要求通过不断的减法操作将数组中的所有元素变为相同。
- 如果数组中本身只有一种元素,说明已经相同,直接返回 0;
- 否则,目标是将数组中所有元素变为 0(任意相同值皆可,为统一处理选择 0)。
具体思路:
-
排序处理:
- 将数组升序排序,便于后续查找与处理。
-
核心变量:
cur
:当前已经处理的目标值,初始为 0;ans
:累计操作步数;idx
:当前正在处理的起始下标,初始化为 1(表示从第一个不同元素开始)。
-
差值与步数计算:
gap = nums[idx] - cur
:表示当前目标值与待处理元素之间的差值;diff = n - idx + 1
:表示当前剩余的不同元素数量;- 利用跳步优化:
steps = (gap + diff - 1) // diff
,即对除法结果上取整,避免差值太大导致多余迭代,题目给出的数据范围为10**18,如果两个相邻元素为1,9999999,那么不使用跳步就会超时。
-
二分查找优化:
- 使用
bisect.bisect_right(nums, cur)
快速确定当前值能影响到哪些元素,快速计算消除之后还剩下多少个不同的元素。
- 使用
import bisect
class Solution(object):
def main(self, nums):
n = len(nums)
if n == 1:
return 0
nums.sort()
cur = 0
ans = 0
idx = 1 # 从第一个不同于最小值的元素开始处理
while idx < n:
diff = n - idx + 1 # 当前剩余未处理的元素数量
gap = nums[idx] - cur # 当前差值
steps = (gap + diff - 1) // diff # 上取整,跳步优化
ans += steps
cur += steps * diff # 累加处理值
# 二分查找:跳过所有小于等于 cur 的元素
idx = bisect.bisect_right(nums, cur)
return ans