力扣刷题👊【462. 最少移动次数使数组元素相等 II】

·  阅读 311
力扣刷题👊【462. 最少移动次数使数组元素相等 II】

这是我参与8月更文挑战的第 9 天,活动详情查看:8月更文挑战

题目链接

462. 最少移动次数使数组元素相等 II

题目描述

给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。

测试用例

输入:[1,2,3]

输出:2

题目分析

前言

各位同学在做这道题的时候,可能会因为没有思路,然后去评论区一看,各个题解一翻,会满脑子问号,“为啥?为啥他们都说要用中位数来解?”,不知道为什么,反倒是用中位数的思路解了出来😶

我们先用一个小的测试样例来进行推算

给出一个已经排好序的测试样例 [0, 1, 2, 6, 8]

通过对数据的观察,可以得知,对首尾的两个数 0,8 最小的移动次数就是在 [0, 8] 之间任意找一个数,他们的固定移动次数都是 8;如果尝试在这个区间外找一个数来计算移动次数,如找 -1,则 0和8 的移动次数则为 10

同理,我们对 1和6 进行最小次数移动的话, [1, 6] 中的任意数,他们固定移动 5次

最后剩下一个中间的数 2,不移动的话,最小次数为 0

对这个参考数的选取则为 [0, 8] ∪ [1, 6] ∪ [2] = 2,他们的最小移动次数就是 8+5+0 = 13

上述思路可以确定,本题的核心点就是寻找中位数,上面分析的是奇数数组,下面分析偶数数组

示例: [0, 1, 2, 6]

1、在 [0, 6] 任意找一个数,固定最小次数 6 2、在 [1, 2] 任意找一个数,固定最小次数 1

中间数的选取条件为 [0, 6] ∪ [1, 2] = [1, 2],即 1或2 都行,最小移动次数为 6+1 = 7

题目答案

上一步分析出来使用中位数是一种合适的解法,那么,代码很容易就出来了

  1. 对给定的数组进行排序
  2. 使用双指针,left 指向 index=0right 指向 index=nums.length-1
  3. 对左右指针指向的数进行绝对值求差
  4. 左右指针往中心靠拢
  5. 处理左右指针在中心处的特殊情况
    1. 左右指针重叠
    2. 左右指针相邻

贴上代码

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);
};
分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改