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

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

给你一个长度为 n 的整数数组 nums ,返回使所有数组元素相等需要的最少移动数。

在一步操作中,你可以使数组中的一个元素加 1 或者减 1 。

 

示例 1:

输入:nums = [1,2,3]
输出:2
解释:
只需要两步操作(每步操作指南使一个元素加 1 或减 1):
[1,2,3]  =>  [2,2,3]  =>  [2,2,2]
示例 2:

输入:nums = [1,10,2,9]
输出:16

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-moves-to-equal-array-elements-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处

题目解析:

每次移动,可以将数组中的某一个数字加 1 或者减 1。求最少移动多少次,能让数组中的数字都相等

分析
假设经过移动以后,所有的数字最终都等于 targettarget。

那么这个 targettarget 的取值有两种情况:在数组取值范围外、在数组取值范围内。

我们分情况讨论。

情况一:targettarget 在数组取值范围外

targettarget 在数组外的含义是 target > 数组最大值target>数组最大值或者 target < 数组最小值target<数组最小值。

假如 targettarget 在数组取值范围之外,那么把所有数字移动到 targettarget 一定比移动到边界的移动次数更多!

以 nums = [1, 2, 3]nums=[1,2,3],target = 4target=4 为例,说明为什么 targettarget 不能在数组之外,见图:

因此,target一定在 nums 的最小值和最大值之间。

情况二:targettarget 在数组取值范围内

当 targettarget在数组取值范围内,那么无论 targettarget 选择何值,对于数组的最小值和最大值而言,它们移动到 targettarget 的次数之和一定是固定的!都等于 最大值 - 最小值最大值−最小值。

下图以 nums = [1, 2, 3, 4, 5, 6]nums=[1,2,3,4,5,6],target = 4target=4 为例,说明当 targettarget 取值在 [1,6][1,6] 范围内,数字 11 与 数字 66 与 targettarget 的距离之和是定值 5;

然后,我们考虑去除 numsnums 的最大值、最小值以后的「子数组」,我们发现 targettarget 也需要选择「子数组」范围之内的数字。

因为「情况一」中已经证明了,选择「子数组」取值范围外的数字不是最优。

如下图所示, nums = [1, 2, 3, 4, 5, 6]nums=[1,2,3,4,5,6] ,当 targettarget 取 11 或者 66 时,对于子数组 [2,3,4,5][2,3,4,5] 不是最优:


综上, targettarget 必须是不断选择 数组(以及子数组)最大值、最小值之间的数字,最终就是「中位数」。

根据上面的分析,可以得出结论:

  • 当数组的长度是偶数时,targettarget 可以选择 22 个中位数任何一个,总移动次数相等。
  • 当数组的长度是奇数时,中位数只有 11 个,因此 targettarget 选择此中位数。

画图说明:

对于数组 nums = [1, 2, 3, 4, 5, 6]nums=[1,2,3,4,5,6] 而言,targettarget 一定选择 33 或者 44。取两者任何一个,结果是相等的。

当数组长度为奇数时,target 一定选择中位数。

当数组长度为奇数时,target 一定选择中位数。

代码实现:

class Solution {
    public:
    int minMoves2(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        const int N = nums.size();
        int mid = nums[N / 2];
        int res = 0;
        for (int n : nums) {
            res += abs(n - mid);
        }
        return res;
    }
};

参考资料

1. 【负雪明烛】图解算法:为什么选择中位数

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章