解题过程
:::info
💡 题目链接
🚀 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数
:::
/**
* @link https://leetcode.cn/problems/minimum-moves-to-equal-array-elements/
* @title 453. 最小操作次数使数组元素相等
* @description 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。
* @param {number[]} nums
* @return {number}
*/
// 💡解法一:利用了反向思维:n-1个元素加1,那就是只有一个元素减1
// 一开始的项目👇🏻
// 📢注意:临界值,数组长度为1,返回0,数组长度为2,两个元素相同则返回0,不相同则返回1
// 第一步:数组元素值由大到小排序,第一个就是最大值
// 第二步:卡在了题干【n-1个元素加1】的操作上了,一时半会想不到如何操作最有效的方式选中n-1个元素加1,
// ❌但是数组元素的最小相等的数也不好计算出来,有点傻这方思路,不过这也许就是大脑最基本的思考吧
// -----------------------------
// ✅最佳解题思路:看了评论的一个高赞解题思路,恍然大悟:【n-1个数同时加1】,就好比每次有一个数自身减一,因为只能做减法,所以数组最后的数只能是最小值(就是数组元素里面最小值的元素)
// 所以,每个元素减去最小值元素之和就是题目答案
// 第一步:数组元素值由大到小排序,第一个就是最大值,最后一个是最小值
// 第二步:循序遍历数组索引,每个元素减去最小值累加即可
var minMoves = function (nums) {
// nums.sort((a, b) => b - a)
let min = Math.min(...nums) // 求数组最小值
let sum = 0
for (let i = 0; i < nums.length; i++) {
sum += nums[i] - min
}
return sum
}
// 💡解法二:找到题干的等式关系(最喜欢的解题技巧之一,很数学,事实证明,算法题来源于数学)
// 数组长度n = nums.length
// 最终结果的数组元素值总和 = 当前数组nums的元素值总和 + n-1个元素加1的操作次数
// 公式:n * x = sum + (n-1)* times
// 左边x就是最后数组中所有元素相等的值,这个值是数组中最小值元素+times(n-1个元素加1的操作次数)得到的值
// x = times+ min
// 将x带进方程 n * (times+min) = sum + (n-1) * times
// 返回最小操作次数:times = sum - n * min
var minMoves = function (nums) {
return nums.reduce((pre, cur) => pre + cur, 0) - nums.length * Math.min(...nums)
}
const result = minMoves([1,2,3]) // 3
// const result = minMoves([1,1,1]) // 0
// const result = minMoves([1, 2, 3, 4]) // 6
console.log(result)
解题感受
一开始考虑到了临界值,数组长度为1,返回0,数组长度为2,两个元素相同则返回0,不相同则返回1
第一步:数组元素值由大到小排序,第一个就是最大值
第二步:卡在了题干【n-1个元素加1】的操作上了,一时半会想不到如何操作最有效的方式选中n-1个元素加1,
❌但是数组元素的最小相等的数也不好计算出来,有点傻这方思路,不过这也许就是大脑最基本的思考吧(以上👆🏻是错误的解题思路)
✅最佳解题思路:利用了反向思维:n-1个元素加1,那就是只有一个元素减1:看了评论的一个高赞解题思路,恍然大悟:【n-1个数同时加1】,就好比每次有一个数自身减一,因为只能做减法,所以数组最后的数只能是最小值(就是数组元素里面最小值的元素)
所以,每个元素减去最小值元素之和就是题目答案
第一步:数组元素值由大到小排序,第一个就是最大值,最后一个是最小值
第二步:循序遍历数组索引,每个元素减去最小值累加即可
这是一道数学题,解法二我更喜欢,很数学,详情看【解题技巧总结】