[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 ...
随机推荐
- 压力测试之badboy和Jmeter的简单使用方法
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 所谓压力测试是指,通过确定一个系统的瓶颈或者不能接收的性能点, ...
- 基于轻量型Web服务器Raspkate的RESTful API的实现
在上一篇文章中,我们已经了解了Raspkate这一轻量型Web服务器,今天,我们再一起了解下如何基于Raspkate实现简单的RESTful API. 模块 首先让我们了解一下"模块&quo ...
- 分享一实战性开源MVC框架<Linux、Windows跨平台开发so easy>
一.引子 开源地址 https://github.com/564064202/Moon.Mvc 欢迎加入开发 .NET Core微软还在发力,但作为商用还有一段距离,很多开发库尚不能用于.NET ...
- 完美解决,浏览器下拉显示网址问题 | 完美解决,使用原生 scroll 写下拉刷新
在 web 开发过程中我们经常遇到,不想让用户下拉看到我的地址,也有时候在 div 中没有惯性滚动,就此也出了 iScroll 这种关于滚动条的框架,但是就为了一个体验去使用一个框架好像又不值得,今天 ...
- Hadoop学习之旅一:Hello Hadoop
开篇概述 随着计算机网络基础设施的完善,社交网络和电商的发展以及物连网的推进,产生了越来越多的大数据,使得人工智能最近几年也有了长足的发展(可供机器学习的样本数据量足够大了),大数据的存储和处理也越来 ...
- 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(五)
(五)注册Website Cloud 1 注册Website Cloud 添加Website Cloud 连接Website Cloud 注意, endpoint 是使用Management Se ...
- Workflow笔记1——工作流介绍
什么是工作流? 工作流(Workflow),是对工作流程及其各操作步骤之间业务规则的抽象.概括.描述.BPM:是Business Process Management的英文字母缩写.即业务流程管理,是 ...
- K60——寄存器
(1)PTx_BASE_PTR为GPIO寄存器结构体基址指针(PTR即point to register,x=A/B/C/D/E) /* GPIO - Peripheral instance base ...
- video/audio在ios/android上播放兼容
1.audio自动播放 <audio src='xxx.mp3' autoplay></audio> 上面是audio标签autoplay属性是自动播放,但是在安卓部分浏览器和 ...
- BCS datetime 时间区间问题
BCS 整合sql表时发现以下问题: datetime字段在列表中带了时区,比如插入12-6号的数据,在sql中显示的是12-5 date类型字段无法正确识别,插入成功但报错 LobSystem (外 ...