[LeetCode] Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等之二
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
参考资料:
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 最少移动次数使数组元素相等之二的更多相关文章
- 462 Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等 II
给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最多为10000.例如:输入:[1,2,3]输出:2说明:只有两个动作是必 ...
- LeetCode Minimum Moves to Equal Array Elements II
原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/ 题目: Given a non-empt ...
- LeetCode Minimum Moves to Equal Array Elements
原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 题目: Given a non-empty i ...
- 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 ...
- 【LeetCode】462. Minimum Moves to Equal Array Elements II 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:排序 方法二:直接找中位数 日期 题目地址: ...
- 【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 ...
- [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 ...
- [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 ...
- 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 ...
随机推荐
- Write thread-safe servlets [reproduced]
If you write Web applications in Java, the servlet is your best friend. Whether you write Java Serve ...
- Hive索引功能测试
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 从Hive的官方wiki来看,Hive0.7以后增加了一个对表建立index的功能,想试下性能是 ...
- centos7查看系统版本,查看机器位数x86-64
前言 由于不经常使用linux,每当使用的时候就是安装软件,安装软件的时候就要选择安装包平台,是32位的还是64位的.这时候突然发现不知道怎么查,于是百度.虽然轻而易举百度出来,但仍旧没有自己的笔记看 ...
- AngularJs学习笔记(制作留言板)
原文地址:http://www.jmingzi.cn/?post=13 初学Anjularjs两天了,一边学一边写的留言板,只有一级回复嵌套.演示地址 这里总结一下学习的过程和笔记.另外,看看这篇文章 ...
- Java进击C#——应用开发之Asp.net
本章简言 上一章中笔者讲到关于Linq和EF的用法.并以hibernate来进行讲解.那么本章笔者来讲一下C#的Asp.Net.即是在B/S模式下开发.现在企业大部分的业务都是面向B/S模式的.所以对 ...
- JWT实现token-based会话管理
上文<3种web会话管理的方式>介绍了3种会话管理的方式,其中token-based的方式有必要从实现层面了解一下.本文主要介绍这方面的内容.上文提到token-based的实现目前有一个 ...
- 导出数据到Excel --使用ExcelReport有感
先看图,这是几个月前用NPOI写的导出数据到Excel,用了上百行代码,而且难控制,导出来也比较难看 excel打开的效果 下面是我用ExcelReport类库导出到Excel的操作 1.首先引用Ex ...
- 设计模式(十二)享元模式(Flyweight Pattern)
一.引言 在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非 ...
- ubuntu学习的简单笔记
l vi编辑器开发步骤 A)输入 vi Hello.java B) 输入 i 插入模式. C)输入 冒号.[保存退出:wq][退出不保存:q!] l 列出当前目录的所有文件:ls 详细信息的列表:ls ...
- Mysql性能优化二
接上一篇Mysql性能优化一 建立适当的索引 说起提高数据库性能,索引是最物美价廉的东西了.不用加内存,不用改程序,不用调sql,只要执行个正确的'create index',查询速度就可能提高百倍千 ...