453. Minimum Moves to Equal Array Elements的C++解法

来源:互联网 发布:ipad软件商店不动 编辑:程序博客网 时间:2024/06/08 10:43

看到这道题的时候就觉得一定有非常简单的算法,但是作为一个数学渣渣用笔算了半天没能找到。只好写了一个最笨的代码按部就班来算,即每次找到最大的一个数,把剩下的数字全部加一,直到所有的数字相等为止。

class Solution {public:int findMax(vector<int>& nums){int a = nums[0];int ai = 0;int i = 1;for (i; i < nums.size(); i++){if (nums[i] > a){a = nums[i];ai = i;}}return ai;}bool ifEqual(vector<int>& nums){int flag = 1,i=1;int temp = nums[0];for (i; i < nums.size(); i++)if (nums[i] != temp) {flag = 0; break;}return flag;}int minMoves(vector<int>& nums) {int sum=0;int maxmum;if (nums.size())while (!ifEqual(nums)){maxmum = findMax(nums);int i = 0;for (i; i < nums.size(); i++)if (i != maxmum) nums[i]++;sum++;}return sum;}};


写出来之后当然是超时的算法。其中一个超时的测试数据是{1,2147483647},很显然步长是2147483647-1,于是我考虑步长一定和数字之差有关。输入另一组比较夸张的数据{2,100,101},输出的结果是197=100-2+101-2,可以猜想这个步长是所有数与最小数字的差之和。多输入了几组数据测试,都验证的我的猜想。

所以最后的代码是:

class Solution {public:int minMoves(vector<int>& nums) {int sum=0;int i = 0;vector<int>::iterator p = min_element(nums.begin(), nums.end());int minimum=distance(nums.begin(),p);for (i; i<nums.size();i++)  sum=sum+nums[i]-nums[minimum];return sum;}};


看了一下题解:

设数字之和为sum,最小数字为min,序列长度为l。经过m步之后,所有数字都变成了x,有等式:

sum+m*(l-1)=x*l

又因为 x=min+m

两式联立可得 m=sum-min*l


int minMoves(vector<int>& nums) {    return accumulate(begin(nums), end(nums), 0L) - nums.size() * *min_element(begin(nums), end(nums));}

使用0L(代表0是long int型)是因为{1,2147483647}会越int的上界。



0 0