Given a non-empty integer array of size n, find the minimum number of moves required to make all array elements equal, where a move is incrementing n - 1 elements by 1.
Example:
Input:
[1,2,3]
Output:
3
Explanation:
Only three moves are needed (remember each move increments two elements):
3.别人有一个和我是同样的思想,不过他的比较简洁,但是我觉得没有做一些输入检测,风格问题。
Example:
Input:
[1,2,3]
Output:
3
Explanation:
Only three moves are needed (remember each move increments two elements):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
1.brute force 暴力法
我们知道,每次找出元素中最大值,然后其余部分加一,如果等于最大值,那么此时最大值就是相等时候元素值,count就是次数。
class Solution {
public
int minMoves(vectorint& nums) {
int count = 0;
for(; ;){
auto max_iterator = max_element(begin(nums), end(nums));
auto min_iterator = min_element(begin(nums), end(nums));
if(max_iterator == min_iterator)
break;
for(auto it=nums.begin(); it!=nums.end(); ++it){
if(it != max_iterator)
++it;
}
++count;
}
return count;
}
};
暴力算法的时间复杂度为O(kn),k是count叠加的次数。
所以这种方法嘛,显然只能TLE了。
2.数学方法
用s来表示元素数目,c表示需要操作的次数,用e1, e2, e3...en数组元素。
1.s=1,c=0,无需增加,天然相等。
2.s=2, 举例 [0, 2] , c=2
[1, 2], c=1
所以 c= diff(e1, e2),两元素之差
3.s = n,c = diff(min(e), e1) + diff(min(e), e2) +...diff(min(e), en),min(e) ∉ e1,e2...en
虽然元素增多了,但是每次改变的是n-1个元素,diff(min(e), e1)表示最小元素平衡e1所花费的代价,去平衡e1时,由于每次n-1个数目需要加1,所以其他需要平衡的元素也会加1,所以diff(min(e), e2)要花费的代价是相对不会变的。
class Solution {
public:
int minMoves(vector<int>& nums) {
const int size = nums.size();
if(size == 0)
return -1;
if(size == 1)
return 0;
auto min_iterator = std::min_element(begin(nums), end(nums));
int min = *min_iterator;
for(auto &i : nums)
i -= min;
return accumulate(begin(nums), end(nums), 0);
}
};
3.别人有一个和我是同样的思想,不过他的比较简洁,但是我觉得没有做一些输入检测,风格问题。
int minMoves(vector<int>& nums) {
return accumulate(begin(nums), end(nums), 0) - nums.size() * *min_element(begin(nums), end(nums));
}