462. Minimum Moves to Equal Array Elements II

来源:互联网 发布:淘宝押金1000怎么上交 编辑:程序博客网 时间:2024/06/11 17:03

step1

把数组排序

step2

> 把排序后的数组**arr = [x1, x2, x3 ... xn]** 视为横轴上的n个整数


x1      x2           x3       ...          xn

------------------------------------------------>  横轴

下面说出一个结论:

那么如果所有数字都变为同一个数a, 这个数必须是排在中间的数(数组若有奇数个数, 就是正中间的数, 若有偶数个, 则取这两个数的闭区间内的任一整数)


证明:

为了方便说明,我们先取一个数组[1, 2, 3, 4, 5, 8]

那么它们在数轴上的显示如下:

1      2         3          4         5                       8

----------------------------------------------------------->


把他们每个头尾都分到一组, 每组有两个。

即(1, 8) (2, 5) (3, 4)


我们考虑(1, 8)这一组。

首先我们易得,题目的目标是找到一个整数n,让所有数字到那个数字的距离之和最小

那么要让距离之和最小,  每一组的两个数字到某个整数的距离之和(以下简称距离之和)都必须尽可能最小。

根据线段两点到第三点的距离之和最短为线段的长度原理,

要让(1, 8)的距离之和尽可能小,取点必须在[1, 8]内。

同理,

要让(2, 5)的距离之和尽可能小,取点必须在[2, 5]内

所以,我们发现,所要寻找的那个整数n的范围最后被限制在最中间的两个数3与4之间,我们随意取[3, 4]中的一个整数,便可让所有组的距离之和最小。

所以此时的答案是各组的线段长度之和。


当数组长度为奇数个时

根据上面的思想,我们易得答案就是

先排序,

需要“向其靠拢”的数是最中间的那个数

然后把那个数以外的数两两分组,

把这些线段的长度相加即可。


class Solution {public:    int minMoves2(vector<int>& nums) {        sort(nums.begin(), nums.end()); // 排序        int len = nums.size();        int mid = nums[len / 2]; // 找到中间的数        int total = 0;        for(int i = 0; i < len / 2; i++){ // 把每个数到中间数的距离相加, 得到result            int latter = nums[len - 1 - i];            int former = nums[i];            int dis = latter - former;            total += dis;        }        return total;    }};



阅读全文
0 0