[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 ...
随机推荐
- 学习SpringMVC——你们要的REST风格的CRUD来了
来来来,让一下,客官,您要的REST清蒸CRUD来了,火候刚刚好,不油不腻,请慢用~~~ 如果说前面是准备调料,洗菜,切菜,摆盘,那么今天就来完整的上道菜,主要说的是基于REST风格实现数据的增删改查 ...
- docker对数据卷容器进行备份
转载请注明出处 官网的数据以及各大博客都没有对这个的具体说明,本人也是理解了好久. 我们使用docker的过程中,使用共享的数据卷是经常的,那么.我们要怎么进行备份呢? 首先,我们得了解下面4个命 ...
- js正则表达式校验非正整数:^((-\d+)|(0+))$
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 如何实现一个php框架系列文章【6】mysql数据库
实现一个mysql数据库封装需要考虑的问题 使用方便性 采用直接sql语句操作方式.只要会写sql语句,那么将没有其他学习成本. uctphp框架提供的dba辅助封装类,用会之后将爱不释手. 使用前需 ...
- linux grep命令
linux grep命令1.作用Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expressio ...
- 数据仓库开发——Kettle使用示例
Kettle是一个开园ETL工具,做数据仓库用Spoon. 工具:下载Spoon,解压即可用 1.认识常用组件: 表输入 插入\更新 数据同步 文本文件输出 ...
- 关于Linux下转换oracle字符集
前阵子给以同事导oracle数据库,但是发现导入后数据都是乱码,下面是自己解决这个问题的一些小整理. 比如: #su oralce $export ORACLE_SID=orcl $export OR ...
- JavaScript 9种类型
Undefined . Null . Boolean . String . Number . Object . Reference .List .Completion
- js获取页面url
设置或获取对象指定的文件名或路径. window.location.pathname例:http://localhost:8086/topic/index?topicId=361alert(windo ...
- px-rem 一个将px转换为rem的工具
将px转换为rem的工具,github地址:https://github.com/finance-sh/px-rem 怎样转换静态文件 安装: npm install px-rem -g 然后跑下命令 ...