Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where a move is incrementing a selected element by 1 or decrementing a selected element by 1.

You may assume the array's length is at most 10,000.

Example:

Input:
[1,2,3] Output:
2 Explanation:
Only two moves are needed (remember each move increments or decrements one element): [1,2,3] => [2,2,3] => [2,2,2]

这道题是之前那道Minimum Moves to Equal Array Elements的拓展,现在我们可以每次对任意一个数字加1或者减1,让我们用最少的次数让数组所有值相等。一般来说这种题目是不能用暴力方法算出所有情况,因为OJ一般是不会答应的。那么这道题是否像上面一道题一样,有巧妙的方法呢?答案是肯定的。下面这种解法实际上利用了之前一道题Best Meeting Point的思想,是不感觉很amazing,看似完全不相干的两道题,居然有着某种内部联系。我们首先给数组排序,那么我们最终需要变成的相等的数字就是中间的数,如果数组有奇数个,那么就是最中间的那个数字;如果是偶数个,那么就是中间两个数的区间中的任意一个数字。而两端的数字变成中间的一个数字需要的步数实际上就是两端数字的距离,讲到这里发现是不是就和这道题Best Meeting Point的思路是一样了。那么我们就两对两对的累加它们的差值就可以了,参见代码如下:

解法一:

class Solution {
public:
int minMoves2(vector<int>& nums) {
int res = , i = , j = (int)nums.size() - ;
sort(nums.begin(), nums.end());
while (i < j) {
res += nums[j--] - nums[i++];
}
return res;
}
};

既然有了上面的分析,我们知道实际上最后相等的数字就是数组的最中间的那个数字,那么我们在给数组排序后,直接利用坐标定位到中间的数字,然后算数组中每个数组与其的差的绝对值累加即可,参见代码如下:

解法二:

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

上面的两种方法都给整个数组排序了,时间复杂度是O(nlgn),其实我们并不需要给所有的数字排序,我们只关系最中间的数字,那么这个stl中自带的函数nth_element就可以完美的发挥其作用了,我们只要给出我们想要数字的位置,它就能在O(n)的时间内返回正确的数字,然后算数组中每个数组与其的差的绝对值累加即可,参见代码如下:

解法三:

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

下面这种方法是改进版的暴力破解法,它遍历了所有的数字,让每个数字都当作最后相等的值,然后算法出来总步数,每次和res比较,留下较小的。而这种方法叼就叼在它在O(1)的时间内完成了步数统计,那么这样整个遍历下来也只是O(n)的时间,不过由于还是要给数组排序,所以整体的时间复杂度是O(nlgn),这已经能保证可以通过OJ啦。那么我们来看看如何快速计算总步数,首先我们给数组排序,我们假设中间某个位置有个数字k,那么此时数组就是:nums[0], nums[1], ..., k, ..., nums[n - 1], 如果i为数字k在数组中的坐标,那么有k = nums[i],那么总步数为:

Y = k - nums[0] + k - nums[1] + ... + k - nums[i - 1] + nums[i] - k + nums[i + 1] - k + ... + nums[n - 1] - k

= i * k - (nums[0] + nums[1] + ... + nums[i - 1]) + (nums[i] + nums[i + 1] + ... + nums[n - 1]) - (n - i) * k

= 2 * i * k - n * k + sum - 2 * curSum

那么我们只要算出sum和curSum就可以快速得到总步数了,数组之和可以通过遍历数组计算出来,curSum可以在遍历的过程中累加,那么我们就可以算出总步数,然后每次更新结果res了,参见代码如下:

解法四:

class Solution {
public:
int minMoves2(vector<int>& nums) {
sort(nums.begin(), nums.end());
long long sum = accumulate(nums.begin(), nums.end(), );
long long res = LONG_MAX, curSum = ;
int n = nums.size();
for (int i = ; i < n; ++i) {
long long k = nums[i];
curSum += k;
res = min(res, * k * (i + ) - n * k + sum - * curSum);
}
return res;
}
};

类似题目:

Minimum Moves to Equal Array Elements

Best Meeting Point

参考资料:

https://discuss.leetcode.com/topic/68764/5-line-solution-with-comment

https://discuss.leetcode.com/topic/68884/c-average-o-n-nth_element-solution

https://discuss.leetcode.com/topic/68736/java-just-like-meeting-point-problem

https://discuss.leetcode.com/topic/68900/simple-c-sort-and-find-solution-with-detailed-explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等之二的更多相关文章

  1. 462 Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等 II

    给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最多为10000.例如:输入:[1,2,3]输出:2说明:只有两个动作是必 ...

  2. LeetCode Minimum Moves to Equal Array Elements II

    原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/ 题目: Given a non-empt ...

  3. LeetCode Minimum Moves to Equal Array Elements

    原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 题目: Given a non-empty i ...

  4. Leetcode-462 Minimum Moves to Equal Array Elements II

    #462.   Minimum Moves to Equal Array Elements II Given a non-empty integer array, find the minimum n ...

  5. 【LeetCode】462. Minimum Moves to Equal Array Elements II 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:排序 方法二:直接找中位数 日期 题目地址: ...

  6. 【LeetCode】462. Minimum Moves to Equal Array Elements II

    Given a non-empty integer array, find the minimum number of moves required to make all array element ...

  7. [LeetCode] Minimum Moves to Equal Array Elements 最少移动次数使数组元素相等

    Given a non-empty integer array of size n, find the minimum number of moves required to make all arr ...

  8. [Swift]LeetCode462. 最少移动次数使数组元素相等 II | Minimum Moves to Equal Array Elements II

    Given a non-empty integer array, find the minimum number of moves required to make all array element ...

  9. 462. Minimum Moves to Equal Array Elements II

    Given a non-empty integer array, find the minimum number of moves required to make all array element ...

随机推荐

  1. Zip 压缩和解压技术在 HTML5 中的应用

    JSZip 是一款可以创建.读取.修改 .zip 文件的 javaScript 工具.在 web 应用中,免不了需要从 web 服务器中获取资源,如果可以将所有的资源都合并到一个 .zip 文件中,这 ...

  2. parseInt实例详解

    parseInt() 函数可解析一个字符串,并返回一个整数. parseInt(string, radix) 参数 描述 string 必需.要被解析的字符串. radix 可选.表示要解析的数字的基 ...

  3. request 对象和 response 对象

    Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象 HttpServletResponse HttpServletR ...

  4. 充电时间 Go中的数组、切片、map简单示例

    数组是固定长度的,依稀让我想起了VB:切片是动态的:map一般是键值对 package main import ( "fmt" ) func main() { var userna ...

  5. php设计模式总结-工厂模式

    使用工厂模式的目的或目标? 工厂模式的最大优点在于创建对象上面,就是把创建对象的过程封装起来,这样随时可以产生一个新的对象.减少代码进行复制粘帖,耦合关系重,牵一发动其他部分代码. 通俗的说,以前创建 ...

  6. CSS类似微软中国首页的竖向选项卡

    效果体验:http://hovertree.com/texiao/css/24/ 源码下载:http://hovertree.com/h/bjaf/hardklps.htm 代码如下: <!DO ...

  7. low security dvwa--SQL Injection

    登录dvwa后,点击左边的"SQL Injection",出现以下界面: 下面做一些学习总结. 第一步:用 "order by n" 获得表中的属性列数,它的意 ...

  8. SYN Flood测试

    由于工作需要对公司进行SYN Flood测试,在网上查了些资料,Youtube上找到最多的方法就是hping3工具来实现, 该工具已经预装在Kali下,具体操作用一条命令即可实现. hping3 -S ...

  9. 通过安装一个描述文件在控制台获得设备的udid

    在我的这篇博客里面说明了本地获得设备udid的方法,但是只能在模拟器中获得http://www.cnblogs.com/liyy2015/p/6090204.html 当然可以在设备上集成苹果的MDM ...

  10. android 自定义控件——(三)水平线、虚线

    ----------------------------------View虚线或者直线(源代码下有属性解释)--------------------------------------------- ...