两道有意思的leetcode数学题

问题来源:

点击打开链接


问题描述:

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]

思路与解决方案:

思路原作者:

W
 

let's define sum as the sum of all the numbers, before any moves; minNum as the min number int the list; n is the length of the list;

After, say m moves, we get all the numbers as x , and we will get the following equation

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

and actually,

  x = minNum + m

and finally, we will get

  sum - minNum * n = m

So, it is clear and easy now.


class Solution {
public:
    int minMoves(vector<int>& nums) {
        if(nums.size()<=1)
          return 0;
        long final=0,maxnum=nums[0],minnum=nums[0],sum=0;
        for(int i=0;i<nums.size();++i)
        {
          sum+=nums[i];
          if(nums[i]<minnum)
            minnum=nums[i];
        }
        return sum-minnum*nums.size();
    }
};


问题来源:

点击打开链接


问题描述:

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]

思路和解决方案:

思路原作者:

 

Suppose you have two endpoints A and B, when you want to find a point C that has minimum sum of distance between AC and BC, the point C will always between A and B. Draw a graph and you will understand it. Lets keep moving forward. After we locating the point C between A and B, we can define that
dis(AC) = c - a; dis(CB) = b - c;
sum = dis(AC) + dis(CB) = b - a.
b - a will be a constant value, given specific b and a. Thus there will be no difference between points among A and B.

In this problem, we set two boundaries, saying i and j, and we move the i and j to do the computation.

Hope it helps.

更严谨的证明:

原作者:

 

If the minimum number of moves makes all array entries {xi=1:N} to some value x, it can be proved that the optimal value x must be the median of {xi=1:N} (or any integer between the two central entries).

I have posted a rigorous math proof using triangle inequality here in problem "Best Meeting Point": https://discuss.leetcode.com/topic/53593/strict-mathematics-proof-to-minimize-sum_i-abs-x-x_i-using-triangle-inequality

    int minMoves2(vector<int>& nums) {
      sort(nums.begin(), nums.end()); int n = nums.size(), res = 0;
      for (int i = 0; i < n/2; ++i) res += (nums[n-1-i]-nums[i]);
      return res;
    }

Problem: Given a sequence {xi=1:N}, prove that median x minimizes function f(x) := Σi=1:N | x-xi |.

Proof: Without losing generality, assume {xi=1:N} is sorted. Simply grouping the sum into pairs:

  • f(x) = Σi=1:N/2 (| x-xi | + | x-xN+1-i |) + (N%2)*| x-xN/2+1 |.

Note that we don't have the last term if N is even since they are all grouped into pairs. I will explain why we need to (have to) group the sum in such a form later.

Using triangle inequality, |x-xi| + |x-xN+1-i| >= |xN+1-i - xi| = xN+1-i - xi, and the fact N%2 >= 0, so we can find a lower bound for f

  • f(x) >= Σi=1:N/2 (xN+1-i - xi),

which means if we could actually pick an x to achieve this value, we find the optimal x!

Actually, inequality |x-xi| + |x-xN+1-i| >= |xN+1-i - xi| achieves equality if and only if x is in [xi, xN+1-i]. Since {xi=1:N} is increasing, closed interval sequence { [xi, xN+1-i] }i=1:N/2 is nested, and so they have non-empty common intersection [xN/2, xN-N/2+1]. This is critical, and this is why we need to design the grouping like this. Now it is trivial to see that picking any value in the intersection [xN/2, xN-N/2+1] will reach the minimum if N is even, and only x = xN/2+1 can reach the minimum if N is odd (since we also have to make |x-xN/2+1| zero).


解决方案:

class Solution {
public:
    int minMoves2(vector<int>& nums) {
     sort(nums.begin(),nums.end());
     int i=0,j=nums.size()-1,Ret=0;
     while(i<j)
     {
         Ret+=(nums[j--]-nums[i++]);
     }
     return Ret;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值