这是我参与8月更文挑战的第 9 天,活动详情查看:8月更文挑战web
给定一个非空整数数组,找到使全部数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您能够假设数组的长度最多为10000。数组
输入:[1,2,3]markdown
输出:2svg
前言oop
各位同窗在作这道题的时候,可能会由于没有思路,而后去评论区一看,各个题解一翻,会满脑子问号,“为啥?为啥他们都说要用中位数来解?”,不知道为何,反却是用中位数的思路解了出来😶post
咱们先用一个小的测试样例来进行推算测试
给出一个已经排好序的测试样例 [0, 1, 2, 6, 8]ui
经过对数据的观察,能够得知,对首尾的两个数 0,8 最小的移动次数就是在 [0, 8] 之间任意找一个数,他们的固定移动次数都是 8;若是尝试在这个区间外找一个数来计算移动次数,如找 -1,则 0和8 的移动次数则为 10url
同理,咱们对 1和6 进行最小次数移动的话, [1, 6] 中的任意数,他们固定移动 5次
最后剩下一个中间的数 2,不移动的话,最小次数为 0
对这个参考数的选取则为 [0, 8] ∪ [1, 6] ∪ [2] = 2
,他们的最小移动次数就是 8+5+0 = 13
上述思路能够肯定,本题的核心点就是寻找中位数,上面分析的是奇数数组,下面分析偶数数组
示例: [0, 1, 2, 6]
一、在 [0, 6] 任意找一个数,固定最小次数 6 二、在 [1, 2] 任意找一个数,固定最小次数 1
中间数的选取条件为 [0, 6] ∪ [1, 2] = [1, 2]
,即 1或2 都行,最小移动次数为 6+1 = 7
上一步分析出来使用中位数是一种合适的解法,那么,代码很容易就出来了
left
指向 index=0
,right
指向 index=nums.length-1
贴上代码
var minMoves2 = function(nums) {
nums.sort((a, b) => a - b);
let index = (nums.length - 1) / 2;
let center = Math.floor((nums[Math.floor(index)] + nums[Math.ceil(index)])) / 2;
return nums.reduce((a, b) => a + Math.abs(b - center), 0);
};
复制代码