zoukankan      html  css  js  c++  java
  • 相遇问题(力扣第462题)

      试想两个人,在一条无限长的直线上的两个不同位置,两个人怎么做才能走最少的步数相遇,那就是两个面对面同时朝着对方走,就可以以最少的步数相遇。那么,来看一下这个题:

    题目:

      给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。

    例如:

    输入:
    [1,2,3]
    
    输出:
    2
    
    说明:
    只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1): 
    
    [1,2,3]  =>  [2,2,3]  =>  [2,2,2]

    分析:

      这就是一个典型的相遇问题,可以把数组中的所有元素想象成在一个数轴上的点,然后通过移动使得这些点都相遇在某一点,如何使得移动的次数最少?那我们首先,可以对这些点进行一下排序,假设相遇点是x,那么数组中经过排序的任意两个数a,b(a<b),都有a<=x<=b,这两个点相向移动才会使得移动的距离最小,所以移动的次数是 (b-x)+(x-a),其实就是b-a;

      那么我们要求的是所有数的到达共同的相遇点所移动的距离,其实就是求两两较大数和较小数之间的差值。那我们就假定x是共同的相遇点,它将排序后的数组中数一分为2,即较大的数向左移动,较小的数向右移动,那就使用l和r这两个指针,起始时分别指向数组首部和尾部,移动的距离是num[r] - x + x- num[l],即num[r] - num[l],直到两个指针相遇就结束。

      要知道x其实就是较大那部分数和较小那部分中间的任何一个整数,它的值具体是多少没有意义,它的意义在于它相当就是这组数的中位数,这组数要想以最小的移动次数变为全部相等的数,那么就都朝着x进行变化即可。那么就可以形象的理解成为,一对一对的两个数进行着相向移动,二者移动距离之和,一定是二者的数值相减的结果。用数学表达式表示就是:

    res = (x-a1) + (x-a2) + (x-a3)  + ……(an-1-x)  + (an-x)
    如果n为偶数,那么x正好全部被抵消掉;如果为奇数,那么最中间的那个数就是中位数,和x相等,二者相减直接就为0;

     

    代码:

    public int minMoves2(int[] nums) {
        if (nums == null || nums.length == 0){
            return 0;
        }
        Arrays.sort(nums);
        int l = 0;
        int r = nums.length - 1;
        int res = 0;
        while (l <= r){
            res += nums[r] - nums[l];
            l++;
            r--;
        }
    
        return res;
    }
  • 相关阅读:
    lnmp thinkphp在linux上支持pathinfo
    position
    whereis命令
    Css transition
    CSS3 2D 转换
    asp.net缓存(转)
    Quartz.net开源作业调度框架使用详解(转)
    .Net开源工作流Roadflow的使用与集成(转)
    反射中 GetCustomAttributes
    ASP.NTE 5 Target framework dnx451 and dnxcore50(转)原文:http://www.cnblogs.com/xishuai/p/aspnet5-target-framework-dnx451-and-dnxcore50.html
  • 原文地址:https://www.cnblogs.com/yxym2016/p/13054444.html
Copyright © 2011-2022 走看看