【算法刷题】蓝桥杯/AtCoder:删除元素后的中位数问题(Symmetry / Median)

【算法刷题】蓝桥杯/AtCoder:删除元素后的中位数问题(Symmetry / Median)

📌 题目描述与考点

  • 问题核心 :给定一个包含 NNN 个元素的数组(NNN 为偶数)。依次计算删去第 iii 个元素 XiX_iXi 后,剩余 N−1N-1N−1 个元素组成的数组的中位数,并按原始顺序输出这 NNN 个答案。
  • 核心考点 :中位数性质 、思维转换 、原序与排序序列的分离处理。

🔍 核心思路解析

1. 经典错误思路剖析

❌ 错误做法 1 :对于每个 XiX_iXi,都复制一份数组、删除 XiX_iXi、重新排序找中位数。

  • 耗时 :每次排序耗时 O(Nlog⁡N)\mathcal{O}(N \log N)O(NlogN),总共 NNN 次,时间复杂度高达 O(N2log⁡N)\mathcal{O}(N^2 \log N)O(N2logN),遭遇 TLE(超时)。

❌ 错误做法 2 :直接按原数组索引前 N/2N/2N/2 个输出较大中位数,后 N/2N/2N/2 个输出较小中位数。

  • 原因 :忽略了原数组的输入顺序是无序的,删除元素的影响取决于该元素在数值大小排序后的位置,而非输入顺序。

2. 正确的数学推导(分类讨论)

将原数组按数值升序排序,设排序后的数组为 AAA:

  • 原数组中第 N/2N/2N/2 小的数为 AN/2−1AN/2 - 1AN/2−1(记为 later)。
  • 原数组中第 N/2+1N/2 + 1N/2+1 小的数为 AN/2AN/2AN/2(记为 former)。

对于任意被删除的元素 XiX_iXi(对应原输入数组 BiBiBi):

  1. 若 Xi≤AN/2−1X_i \le AN/2 - 1Xi≤AN/2−1(即 XiX_iXi 属于排序后数组的左半部分):

    • 删掉 XiX_iXi 后,左半边少了一个小元素,中位数指针必须向右偏移补位。
    • 新的中位数变为较大的那个数:former(即 AN/2AN/2AN/2)。
  2. 若 Xi≥AN/2X_i \ge AN/2Xi≥AN/2(即 XiX_iXi 属于排序后数组的右半部分):

    • 删掉 XiX_iXi 后,右半边少了一个大元素,中位数指针不受影响。
    • 新的中位数变为较小的那个数:later(即 AN/2−1AN/2 - 1AN/2−1)。

💻 C++ 完整 AC 代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    // 开启快速 I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    if (!(cin >> n)) return 0;

    vector<int> a(n); // 用于升序排序
    vector<int> b(n); // 维护原始输入顺序

    for (int i = 0; i < n; i++) {
        cin >> a[i];
        b[i] = a[i];
    }

    // 升序排序
    sort(a.begin(), a.end());

    // 提取排序后的两大关键中位数边界
    int later = a[n / 2 - 1]; // 较小的中位数候选
    int former = a[n / 2];    // 较大的中位数候选

    // 按原始输入顺序判断并输出
    for (int i = 0; i < n; i++) {
        if (b[i] <= later) {
            cout << former << "\n";
        } else {
            cout << later << "\n";
        }
    }

    return 0;
}

❌ 易错点总结

  • 混淆原始顺序与排序后顺序 :必须使用两个数组,一个数组 bbb 保留原始输入顺序进行遍历判断,另一个数组 aaa 排序提取中位数界限。
  • 边界条件判断 :分支条件为 b[i] <= later(或 b[i] < former),注意相等时的归属处理。

⏱️ 复杂度分析

  • 时间复杂度 :O(Nlog⁡N)\mathcal{O}(N \log N)O(NlogN)
    仅需在开始时对数组进行一次排序 O(Nlog⁡N)\mathcal{O}(N \log N)O(NlogN),后续输出只需要遍历一次数组 O(N)\mathcal{O}(N)O(N),轻松 AC。
  • 空间复杂度 :O(N)\mathcal{O}(N)O(N)
    需要两个大小为 NNN 的 vector 数组存储原始数据和排序数据。
相关推荐
罗西的思考5 小时前
【Agentic RL】Dressage Staleness 控制深度分析
人工智能·算法·机器学习
quaer5 小时前
弗洛伊德算法--判圈法寻找环的入口O(n) O(1)
数据结构·算法
高晶6 小时前
无乘法器实现LC二阶滤波器:基于移位运算的快速算法与四种精度推导
算法·设计模式·程序员
ysbfsy6 小时前
大数计算思路
算法
高晶6 小时前
主从自动分配算法:平均值乘以设备数一半的选举基准值解析
算法·设计模式·程序员
学电子她就能回来吗7 小时前
LeetCode Hot 100|普通数组专题学习笔记(零基础版)
笔记·算法·leetcode
用户老李7 小时前
反向传播计算梯度举例
算法
niyongsheng7 小时前
多智能体连续时间内路径规划:AA-SIPP(m) 的 Rust 实现与算法
算法·rust·机器人
302wanger8 小时前
DeepSeek-V4.1-Flash-1017 免费用到1024,速来
算法
lisw058 小时前
微分与积分的本质区别解析
算法·数学建模·极限编程