【算法刷题】蓝桥杯/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 数组存储原始数据和排序数据。
相关推荐
longlongzihan2 小时前
LeetCode 17电话号码的字母组合:回溯算法(DFS)详解
c++·算法·leetcode·深度优先
封印师请假去地球钓鱼2 小时前
边解边变的问题:从“决策依赖“一词出发
人工智能·算法
今晚打老虎2 小时前
c++之提高A(前缀和)(第三课)
数据结构·c++·算法
不会就选b4 小时前
算法日常・每日刷题--<贪心>26
数据结构·算法
hetao17338375 小时前
2026-09-29 hetao1733837 的刷题记录
c++·算法
欣欣之王来了6 小时前
AI合规专项:AI算法透明度的合规要求
人工智能·算法
wzdark6 小时前
分块思想在算法优化中的实践与应用4
算法
Because_of_Her16 小时前
dfs-洪水填充技巧
笔记·算法·深度优先·洪水填充
小静AI工程实验室6 小时前
RSA 算法详解:从模幂原理到 OAEP 加密、PSS 签名与 Python 实验
python·算法
xzal126 小时前
GESP Python笔记
笔记·python·算法