【算法刷题】蓝桥杯/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 数组存储原始数据和排序数据。
相关推荐
小雉系统1 天前
BcoreOS安全通信架构:FsSession 抗算法后门安全设计
算法·安全·架构
唐墨1231 天前
linux kernel 比较数据大小的宏定义
linux·算法
拂拉氏1 天前
【知识讲解-题目讲解】 统计满足K约束的子字符串数量2 (滑动窗口+前缀和+二分查找+分析)
算法·前缀和·二分查找·滑动窗口
通信小呆呆1 天前
电子战抗干扰技术:当“不被干扰”成为一种系统
算法·通信·mimo·isac
笑容掩饰我的失落1 天前
区块链从小白到精通(八):从零实现一个标准 ERC-20 代币(完整可运行代码)
算法·区块链·php·智能合约·哈希算法
Severus_black1 天前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl
2601_967979121 天前
机器学习必修课:经典算法与Python实战
python·算法·机器学习·实战·课程
程序猿打工仔1 天前
计算机基础(C语言)考编、专技岗
c语言·开发语言·算法
通信小呆呆1 天前
电子战干扰技术:从“蛮力压制”到“精准欺骗”,再到“认知博弈”
算法·通信·isac