leetcode - 最小移动次数使数组元素相等
思路 (假设数组每次都已被排好序)
- 每次使得小于等于最大值的n-1的数字加1,直接暴力求解会超时
- 改进一: 为了让最小元素等于最大元素,至少需要数组中最大值-最小值次, 所以以此为基础再次暴力求解(参见下面第一个python代码)
- 改进二: 整个求解过程就是最小不断去追最大, 直到两者相等为止。\(max_{0}\)为原始数组中的最大值, 更新后的\(max_{1}\)为原始数组的第n-1个加上上一次的\((max-min)\),\(max_{2}\)为原始数组的第n-2个加上上一次的\((max-min)\). . . 且可以发现每一次的min都是上一次的max,
- 最终的移动次数就是\(moves = \sum_{i=1}^{n-1}(a[i]-a[0])\) 其中n为数组的长度
# 暴力求解 -> 超时
class Solution:
def minMoves(self, nums) -> int:
nums = sorted(nums)
if len(nums) == 2:
return nums[1]-nums[0]
if len(nums) == 1 or len(nums) == 0:
return 0
if nums[0] == nums[-2]:
return nums[-1] - nums[0]
# 达到目的必然会移动不少于max-min步, 因为最后的结果的max一定是大于原有max的, 所以min至少要先移动到原有max那里去
count = nums[-1]-nums[0]
for i in range(len(nums) - 1):
nums[i] += count
nums = sorted(nums)
while nums[0] != nums[-1]:
for i in range(len(nums)-1):
nums[i] += 1
count += 1
nums = sorted(nums)
return count
# 学习官方求解 修改后的 -> 通过
# 其实优化过程, 就是个找规律的过程
class Solution:
def minMoves(self, nums):
sums = sum(nums)
mins = min(nums)
mul = mins*len(nums)
return sums - mul
总结
只要能找到规律, 优化就不是事儿