Topic description:
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): [1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
Function to be done:
int minMoves(vector<int>& nums)
illustrate:
1. This question seems interesting.
Let's take an example of [1, 2, 3, 4] to see if we can find any rules.
[1,2,3,4], select the smallest 3 elements inside +1
[2,3,4,4], select the smallest 3 elements inside +1
[3,4,5,4], select the smallest 3 elements inside +1
[4,5,5,5], select the smallest 3 elements inside +1
[5,6,6,5], select the smallest 3 elements inside +1
[6,7,6,6], select the smallest 3 elements inside +1
[7,7,7,7], select the smallest 3 elements inside +1
We can find that when processing a vector, the smallest n-1 elements in it are always selected to +1. In this way, our intuition tells us that this is the fastest.
Indeed, if in the step [3,4,5,4], we do not choose the smallest three elements to process, but choose 4,5,4 to +1, the result will be [3,5,6, 5]. No matter how you deal with it later, it will not reach [7,7,7,7].
Pick the smallest n-1 elements to process, this is the fastest way to get to "all values equal".
It stands to reason that, knowing this information, we can write code to simulate this process:
Each time the largest element is found, then the other elements except the largest element are +1.
Keep repeating processing until all elements are equal.
Output the number of times to repeat the process.
But I always feel that there is a smell that can directly calculate the output.
Let's go back and look again.
2. Mathematical methods
n-1 numbers + 1, if the process is repeated count times, then it is (n-1)*count, plus the value of the original n numbers, the result will be equal to all equal numbers (set as t)*n.
That is (n-1)*count+(the value of n numbers)=t*n.
The key is the value of t.
Let's go back and look at the example given in 1. In each processing, the minimum value of 1 is involved. A total of 6 times are added, and finally it becomes 7.
Intuition tells us that at the beginning, the minimum value will be added count times, that is, t should be min+count.
If this conclusion holds, the above formula can be solved for count.
Let's try it out, the code is as follows:
int minMoves(vector<int>& nums)
{
int min1=nums[ 0 ];//Record the minimum value
int len= nums.size();
int result=nums[ 0 ];//Record the sum of the values in nums
for ( int i= 1 ;i<len; i++ )
{
result+=nums[i];
if(nums[i]<min1)
min1=nums[i];
}
return result-min1*len;//我们要求的count
}
submit,实测51ms,beats 94.55% of cpp submissions。通过了所有测试样例……
我们的直觉为什么是成立的?笔者在推[1,2,3,4]的时候,觉得直觉的想法应该大致是成立的,但是想给出一个数学上的解释就比较麻烦了。
姑且放过笔者吧……日后被remind到简单又好懂的推理方法再来补充。