惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 小纸条

ruoyiai 启动指南 反向传播 numpy的使用 B 和 B+树 红黑树 ruoyi-vue 梯度下降法 博弈论 离散化 AcWing 907. 区间覆盖 AcWing 906. 区间分组 AcWing 908 最大不相交区间数量 AcWing 905. 区间选点 动态规划经典题 窗口函数 1226. 哲学家进餐 1195. 交替打印字符串 1117. H2O 生成 1116. 打印零与奇偶数 关联子查询
AcWing 104. 货仓选址
小纸条 · 2025-11-22 · via 博客园 - 小纸条

AcWing 104. 货仓选址

一、题目描述

1. 问题核心

在一条数轴上有N家商店,各自的坐标为A₁∼Aₙ。需要在数轴上选择一个位置建立货仓,使得货仓到所有商店的距离之和最小,最终输出这个最小距离和。

2. 输入输出格式

  • 输入:第一行输入整数N(商店数量),第二行输入N个整数(各商店的坐标)。
  • 输出:一个整数,表示货仓到所有商店的最小距离之和。

3. 数据范围与样例

  • 数据范围:1≤N≤100000,0≤Aᵢ≤40000。
  • 输入样例:
4
6 2 9 1
  • 输出样例:12

二、解题思路

1. 核心问题:为什么是中位数?

货仓选址的关键是找到一个位置,使得所有点到该位置的距离之和最小。这一问题的最优解并非平均数,而是中位数,具体推导如下:

假设货仓初始位于最优位置,此时:

  • 货仓左侧有a家商店,右侧有n-a家商店。
  • 左侧商店到货仓的距离和为p,右侧为q,总距离和p+q为最小值。

当货仓向左移动x个单位时,新的总距离和为:

p - a·x + q + (n-a)·x = p+q + (n-2a)·x

由于初始位置是最优解,移动后的总距离和不能减小,因此(n-2a)·x≥0(x>0)。当a=n/2时,n-2a=0,移动货仓不会改变总距离和,此时位置即为中位数,是最优解。

2. 中位数的取值规则

  • 若数组下标从0开始,中位数为排序后数组的a[n/2]。
  • 若数组下标从1开始,中位数为排序后数组的a[n/2 + 1]。
  • 补充说明:中位数所在的“中间范围”内,任意位置的总距离和均相同,无需严格局限于某个点。

三、代码实现

1. 代码整体框架

解题步骤可简化为:输入数据→排序数组→计算各点到中位数的距离和→输出结果。具体代码如下:

   public static int minDistance(int[] arr, int n){
        Arrays.sort(arr);
        int p = arr[n/2];
        int total =0;
        for (int e:arr){
            total+=Math.abs(e-p);
        }
        return total;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] tokens = br.readLine().split(" ");
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = Integer.parseInt(tokens[i]);
        }
        System.out.println(minDistance(a,a.length));
    }

2. 关键代码解释

  • sort:对坐标数组排序是获取中位数的前提,排序后数组按从小到大排列,时间复杂度O(nlogn),适配N=1e5的规模。
  • abs(a[i] - a[n / 2]):计算每个坐标与中位数的距离绝对值,累加后得到最小距离和,时间复杂度O(n)。

四、总结

货仓选址问题的核心是利用“中位数最小化距离和”的数学性质,解题流程简洁高效:排序数组后取中位数,再计算各点到中位数的距离和。该解法时间复杂度为O(nlogn)。

车辆移动到连续位置:最小总步数问题详解

在直线坐标上的优化问题中,“车辆移动到连续位置”是经典题型。本文将从题目分析、思路推导到代码实现,完整拆解这类问题的解题逻辑,帮助你掌握核心解法。

一、题目描述

1. 问题核心

给定 N 辆车在无限长直线上的整数坐标(可负,绝对值最大达 2×10⁹),需将所有车移动到 连续的整数位置(形如 x, x+1, x+2, ..., x+N-1)。每次移动一辆车一步(距离为 1),求最少需要的总步数。

2. 关键约束

  • 车辆初始位置:整数坐标,可正可负,范围无上限(仅绝对值≤2×10⁹)。
  • 目标状态:所有车的位置为连续整数序列,长度为 N。
  • 优化目标:总移动步数最小(每步计 1 次)。

二、解题思路

1. 关键观察

最终目标是让车辆分布在长度为 N 的连续整数区间内,核心是找到合适的起始点 x,使所有车移动到目标序列 [x, x+1, ..., x+N-1] 的总步数最小。

2. 数学转化(核心步骤)

  • 第一步:对原始车辆位置数组 positions 排序,得到有序数组 a[0], a[1], ..., a[N-1]
  • 第二步:定义目标序列 t[i] = x + i(i 从 0 到 N-1),其中 x 是目标序列的起始点。
  • 第三步:总移动步数为各车辆初始位置与目标位置的距离绝对值之和,即:
    总步数 = Σ|a[i] - t[i]| = Σ|a[i] - (x + i)|
    
  • 第四步:简化表达式,令 b[i] = a[i] - i,则总步数转化为:
    总步数 = Σ|b[i] - x|
    
  • 第五步:根据数学性质,当 x 取 b 数组的 中位数 时,绝对值之和最小,这是该问题的最优解。

3. 解题流程总结

  1. 对原始位置数组排序。
  2. 计算辅助数组 b[i] = 排序后的位置[i] - i
  3. 找到 b 数组的中位数,作为最优起始点 x。
  4. 计算所有 |b[i] - x| 的和,即为最小总步数。

三、代码实现与分析

1. 正确代码(Java 版)

    private static long minMoveSteps(long[] positions) {
        int n = positions.length;
        // 创建 b[i] = positions[i] - i
        long[] b = new long[n];
        for (int i = 0; i < n; i++) {
            b[i] = positions[i] - i;
        }
        Arrays.sort(b);
        long x = b[n / 2]; // 中位数
        long total = 0;
        for (int i = 0; i < n; i++) {
            total += Math.abs(b[i] - x);
        }
        return total;
    }

2. 代码关键解析

  • 排序操作:对原始位置数组排序是后续计算 b 数组的基础,确保辅助数组的规律性,时间复杂度 O(NlogN)。
  • 辅助数组 b:通过 positions[i] - i 转化,将“连续位置”的约束转化为“找中位数最小化绝对值和”的经典问题,降低解题难度。
  • 中位数取值:b[n/2] 是数组排序后的下中位数,对于奇偶长度的数组均适用,能保证绝对值和最小。
  • 总步数计算:通过 Math.abs(positions[i] - (x + i)) 还原每个车辆的实际移动距离,累加得到结果,时间复杂度 O(N)。