题解 | #航海#

航海

http://www.nowcoder.com/practice/1ac46a9b79194cb987c0579dfdf3121a

题解一: 数学方法
题解思路: 首先,给出结论给定N个点(x1,x2...xn),要找到使得 :
图片说明
最小得x; 此点比然是其中位数。
证明:首先对N个点排序.假设该点在N个点中xi:
图片说明
如果这个点往右移xi+1
图片说明
两者相减,可得向右移距离变化:
图片说明
xi+1-x1始终大于零,所以当i<=n/2时,(2i - n)小于等于0 上式大于等于0; 当i>=n/2时,(2i-n)大于等于0 上式小于等于0; 随着i逐渐增大,距离先小后大。所以在i = n/2取得最小值。
假设该点不在这N个点中: xi<t1<t2<xi+1,得
图片说明
当i<= n/2 , 上式大于等于0,当i>=n/2, 上式小于等于0; 距离先小后大,所以在i = n/2取得最小值。
复杂度分析:
时间复杂度: ,排序时间
空间复杂度: ,需要申请辅助数组,来保存x,y的值,来进行排序
实现如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型 n
     * @param x int整型vector x
     * @param y int整型vector y
     * @param w int整型vector w
     * @return long长整型
     */
    long long MinimumDistance(int n, vector<int>& x, vector<int>& y, vector<int>& w) {
        // write code here
        vector<int> xt; 
        vector<int> yt;
        for(auto it :x) xt.push_back(it); 
        for(auto it :y) yt.push_back(it);
        sort(xt.begin(),xt.end());  //对x排序
        sort(yt.begin(),yt.end());   //对y排序
        int xlen = x.size(),ylen = y.size();
        double x1 = 0,y1=0;
        int mid1 = xlen/2;
        if(xlen%2==0){
            x1 = xt[mid1]+xt[mid1-1];  //如果长度为偶数,求x中位数
            y1 = yt[mid1]+yt[mid1-1];  
            x1 /= 2;
            y1 /= 2;
        }else {x1 = xt[mid1];y1 = yt[mid1];} 
        double ans = 0;
        for(int i = 0;i<xlen;++i){
           double dis = abs(x1-x[i])+abs(y1-y[i]);  //求距离
           ans += dis*w[i];  //乘上权重
        }
        return (long long)ans;
    }
};

题解二:二分
题解思路 : x,y都可以看出单独计算曼哈顿距离。假设有N个数,并且当前位置为mid,mid左边有x,那么右边有n-x. 假设当前带权曼哈顿距离为dis,如果该点向右移动,新曼哈顿距离为res+z(2x-n);
*
复杂度:**
时间复杂度: : x和y都是单层遍历
空间复杂度: :需要申请辅助数组nums_weight的大小
实现如下:

class Solution {
public:
    long long Manhattandistance(int n, vector<int>& m, vector<int>& w, int max_value){
        long long sum = 0, temp = 0, distance = 0;
        int median;
        vector<long long> nums_weight(max_value + 1, 0);
        for(int i = 0; i < n; i++){
            nums_weight[m[i]] += w[i]; 
            sum += w[i];
        }
        for(int i = 0; i <= max_value; i++){ //找权值中点
            temp += nums_weight[i];
            if(temp >=  sum / 2){
                median = i;
                break;
            }
        }
        for(int i = 0; i < n; i++)
            distance += abs(m[i] - median) * w[i];  //计算带权曼哈顿距离
        return distance;
    }
    long long MinimumDistance(int n, vector<int>& x, vector<int>& y, vector<int>& w) {
        int max_x = 0, max_y = 0;
        for(int i = 0; i < n; i++){ //分别找到 x y 最大值
            max_x = max(max_x, x[i]);
            max_y = max(max_y, y[i]);
        }
        //x维加上y维带权曼哈顿距离
        return Manhattandistance(n, x, w, max_x) + Manhattandistance(n, y, w, max_y);
    }
};
牛客网编程题题解 文章被收录于专栏

本专栏记录在牛客网上AC的每一题,写下题解。 未来2年完成2000编程题的题解。 2021.12.29更新,最进准备毕设,断更了,会尽快做完毕设,继续做这一件事情

全部评论

相关推荐

2025-12-02 02:15
门头沟学院
最近菊厂陆续开了,极力劝退那些拿13级的985硕士,就13级那么点儿薪资,一线城市每个月到手1.8/7/6w,租房2k还是破烂,吃饭2k还是预制菜,买个1k衣服都是聚酯纤维破塑料,稍微出去浪一浪,能留1w就是万岁,要是再有个啥都想买的对象,一线工作一年难存10w。隔壁工地混泥土,钳工,焊工一天800+,还包吃包住。读书18年到985硕士出来就为了进厂螺丝工?还不如从8岁童工开始干活,别人读书完了你工龄18+,混不上领导也是个小头头了。当然专科进来正式工,od都行,一般本科进来13级也OK,毕竟22岁年纪摆在那个地方还不需要太花钱。读硕博的基本26岁,工作两年就要结婚的,兜里没几个崽,连彩礼都要信用贷。菊厂离职的不少,毕竟正常没人受得了9116(梗:再来一次911刷6)。为啥这时候劝?因为刚下班,因为国考刚完,省考下周,就是可惜选调只有当年应届能报。现在回想能拍断大腿。应届生真实好身份,错过这一次,选调,考公,考编,当老师,进医院,研究所,高校,央国企,基本都无缘了,就连报名资格都被剥夺了,可谓是被党和国家遗弃的废材,统称“社会上的”,扔到社会去流浪,被用坏了就扔医院,长期超负载使用,零件修不好基本可以扔火里回炉重造了。体制内奉行找体制内的,都是党和国家选的人才,智力不差,样貌不丑,身材端正,收入稳定,安居房政策福利待遇也OK。因公出行都是报销,周末顺带“游山玩水“,这种体制内单身资源但凡想找对象,去社会上随便吆喝一声都排队。观察一下,基本没什么公务员在相亲,因为早就被邻里邻居抢光了。
哈哈哈,你是老六:就这不去的人大把人干呢,现在不缺人干活,你不干大把干呢,还有那个说农民工赚钱的,那个800+我估计肯定也就那一段时间,哪有这么赚钱,还是一句话,要想存下钱必须花销极低,能省的就不花钱,工资要高点
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务