【算法刷题】蓝桥杯/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 数组存储原始数据和排序数据。
相关推荐
看我眼色行事^ \/ ^2 小时前
2024.05.11 360春招WEB前端编程题
算法
一只肥瘫瘫3 小时前
编码器 PLL 角度与速度观测器原理
人工智能·算法
Nil2083 小时前
leetcode 146LRU缓存
算法·leetcode·缓存
郝学胜_神的一滴4 小时前
干货版《算法导论》18:遍历增删原理、时间复杂度与集合序列实现全解
数据结构·算法
-dzk-4 小时前
【滑动窗口】LC 3.无重复字符的最长子串
算法·滑动窗口
zzxdear4 小时前
用 OR-Tools CP-SAT 求解最简单的柔性作业车间调度(FJSP)
算法
luj_17684 小时前
变频技术核心原理揭秘
服务器·c语言·开发语言·经验分享·算法
rannn_1114 小时前
【力扣hot100】图论专题+模板|DFS、BFS、拓扑排序...
java·算法·leetcode·深度优先·图论
_Narcissus_4 小时前
B树概念及操作笔记(含完整代码实现)
c语言·数据结构·数据库·c++·笔记·b树·算法