【寒假每日一题】货仓选址(个人练习)详细题解+推导证明(第一天)

前言

突然发现自己好久没有更博客了,就写一个寒假每日一题来坚持坚持把,不是软广,不是硬广,只是个人练习,题目来自《算法竞赛进阶指南》,模板题。

题目

在一条数轴上有 N N N 家商店,它们的坐标分别为 A 1 A_1 A1~ A N A_N AN

现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。

为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。

输入格式

  • 第一行输入整数 N N N
  • 第二行 N N N 个整数 A 1 A_1 A1~ A N A_N AN

输出格式

  • 输出一个整数,表示距离之和的最小值。

数据范围

  • 1 ≤ N ≤ 100000 1≤N≤100000 1N100000
  • 0 ≤ A i ≤ 40000 0≤A_i≤40000 0Ai40000
输入样例:
4
6 2 9 1
输出样例:
12

在这里插入图片描述

详细题解

写法1 O ( n l o g n ) O(nlogn) O(nlogn)

#include <iostream>
#include <algorithm>
using namespace std;
const int MaxN = 1000005;

int N;
int A[MaxN];

int main()
{
    cin >> N;
    for (int i = 0; i < N; ++i) cin >> A[i];
    sort(A, A + N);
    
    // 调试
    // for (int i = 0; i < N; ++i) cout << A[i] << " ";
    // cout << endl;
    
    int ans = 0;
    for (int i = 0; i < N; ++i) ans += abs(A[i] - A[N >> 1]);
    cout << ans << endl;
    
    return 0;
}

通过调试代码,假设输入五个数,计算距离和的最小值,可以发现其实就是中位数到各个位置的距离之和。具体地,首先先对数组进行排序,可以发现是奇数个数,中位数即最中间的数——2,那么距离和即 ∣ 1 − 2 ∣ + ∣ 2 − 2 ∣ + ∣ 2 − 2 ∣ + ∣ 3 − 2 ∣ + ∣ 5 − 2 ∣ = 5 |1-2| + |2-2| + |2-2| + |3-2| + |5-2| = 5 12+22+22+32+52=5

在这里插入图片描述
偶数也是一样, ∣ 1 − 2.5 ∣ + ∣ 2 − 2.5 ∣ + ∣ 3 − 2.5 ∣ + ∣ 5 − 2.5 ∣ = 5 |1-2.5| + |2-2.5| + |3-2.5| + |5-2.5| = 5 12.5+22.5+32.5+52.5=5

在这里插入图片描述
最后提交,AC😁
在这里插入图片描述

推导证明

本题用到的最主要的数学知识是 ∣ x − a ∣ + ∣ x − b ∣ > = ∣ a − b ∣ |x-a| + |x-b| >= |a-b| xa+xb>=ab

在这里插入图片描述
通过证明可以看到最优解即中位数。
在这里插入图片描述

写法2 O ( n l o g n ) O(nlogn) O(nlogn)

#include <iostream>
#include <algorithm>
using namespace std;
const int MaxN = 1000005;

int N;
int A[MaxN];

int main()
{
    cin >> N;
    for (int i = 0; i < N; ++i) cin >> A[i];
    sort(A, A+N);
    int ans = 0;
    // for (int i = 0; i < N; ++i) ans += abs(A[i] - A[N >> 1]);
    for (int i = 0; i < N; ++i) ans += A[i] - A[i >> 1]; // 改动位置
    cout << ans << endl;
    
    return 0;
}

最后提交,AC😁
在这里插入图片描述

推导证明

解法2与解法1的本质是一样的,同时还能去掉绝对值,因为 A [ i ] > = A [ i / 2 ] A[i] >= A[i/2] A[i]>=A[i/2]
在这里插入图片描述

写法3 O ( n ) O(n) O(n)

#include <iostream>
#include <algorithm>
using namespace std;
const int MaxN = 1000005;

int N;
int A[MaxN];

int main()
{
    cin >> N;
    for (int i = 0; i < N; ++i) cin >> A[i];
    // sort(A, A+N);
    nth_element(A, A + N/2, A + N); // 改动位置
    int ans = 0;
    for (int i = 0; i < N; ++i) ans += abs(A[i] - A[N >> 1]);
    cout << ans << endl;
    
    return 0;
}

最后提交,AC😁
在这里插入图片描述

推导证明

解法3改进了时间复杂度,从 O ( n l o g n ) O(nlogn) O(nlogn) 变成了 O ( n ) O(n) O(n),相当于去掉了快速排序算法的迭代过程,只是一个随机选择的代码。

下面以一个快排代码为例,整个代码的时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn),其中随机选择的时间复杂度是 O ( n ) O(n) O(n),递归的时间复杂度是 O ( l o g n ) O(logn) O(logn)

int partition(vector<int> &data, int start, int end)
{
    int index = (rand()%(end-start+1))+start;
    swap(data[index], data[start]);
    int pivot = data[start];
    int left=start,right=end;
    while(left!=right){
        while(left<right && data[right]>=pivot){right--;}
        while(left<right && data[left]<=pivot){left++;}
        if(left<right) swap(data[left], data[right]);
    }
    swap(data[left], data[start]);
    return left;
}
void quicksort(vector<int> &data, int start, int end){
    if(start==end) return;
    if(start<end){
        int index = partition(data,start,end);
        quicksort(data,start,index-1);
        quicksort(data,index+1,end);
    }
}

举一反三

可以从一维空间扩展到多维空间。

总结

继续努力,坚持更新,1st打卡。
在这里插入图片描述

我是管小亮 CSDN认证博客专家 TensorFlow PyTorch 图像处理
纸上得来终觉浅,绝知此事要躬行

包括但不局限于机器学习,深度学习,自然语言处理,计算机视觉,知识图谱,还有Python,C++,TensorFlow,Pytorch,Keras,PaddlePaddle等,不定时分享资源(电子书/项目/工具),学习路线,思考,面经等!!!
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页