当前位置: 首页 > news >正文

牛客热题:数据流中的中位数

📟作者主页:慢热的陕西人

🌴专栏链接:力扣刷题日记

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

在这里插入图片描述

文章目录

  • 牛客热题:数据流中的中位数
    • 题目链接
    • 方法一:直接插入排序
      • 思路
      • 代码
      • 复杂度
    • 方法二:堆
      • 思路
      • 代码
      • 复杂度

牛客热题:数据流中的中位数

题目链接

数据流中的中位数_牛客题霸_牛客网 (nowcoder.com)

方法一:直接插入排序

思路

插入:

  • 对于每次的插入:
    • 如果序列为零:直接插入
    • 如果序列中的值均小于当前要插入的值:直接插入到序列的尾部
    • 找到序列中第一个比当前要插入的值大的位置,然后将当前的值插入到这个位置,将后续的序列向后挪

计算中位数:

  • 对于偶数的情况
    • 我们直接返回第N / 2 和N / 2 - 1 个元素的平均值即可
  • 对于奇数的情况
    • 我们直接返回N / 2个元素

代码

#include <vector>
class Solution {
public:void Insert(int num) {int n = v.size();if(n == 0) {v.push_back(num);return ;}else{auto it = lower_bound(v.begin(), v.end(), num);v.insert(it, num);}}double GetMedian() { int n = v.size();if(n == 1) return v[0];if(n % 2 == 1){return v[n / 2];}else return (v[n / 2] + v[n / 2 - 1]) / 2;}private:vector<double> v;};

复杂度

时间复杂度:O( N 2 N^2 N2) ,因为每次插入都需要在前面的元素中遍历找到对应的位置,所以每个元素的插入的时间复杂度是O(N),因此时间复杂度为O( N 2 N^2 N2)

空间复杂度:O(N) , 只额外使用了一个对应的vector容器来存储

方法二:堆

思路

中位数是指:有序数组中中间的那个数。则根据中位数可以把数组分为如下三段:
[0 ... median - 1], [median], [median ... arr.size() - 1],即[中位数的左边,中位数,中位数的右边]

那么,如果我有个数据结构保留[0…median-1]的数据,并且可以O(1)时间取出最大值,即arr[0...median-1]中的最大值
相对应的,如果我有个数据结构可以保留[median + 1 ... arr.size() - 1] 的数据, 并且可以O(1)时间取出最小值,即
arr[median + 1 ... arr.size() - 1] 中的最小值。
然后,我们把[median]即中位数,随便放到哪个都可以。

假设[0 ... median - 1]的长度为l_len, [median + 1 ... arr.sise() - 1]的长度为 r_len.
1.如果l_len == r_len + 1, 说明,中位数是左边数据结构的最大值
2.如果l_len + 1 == r_len, 说明,中位数是右边数据结构的最小值
3.如果l_len == r_len, 说明,中位数是左边数据结构的最大值与右边数据结构的最小值的平均值。

说了这么多,一个数据结构可以O(1)返回最小值的,其实就是小根堆,O(1)返回最大值的,其实就是大根堆。并且每次插入到堆中的时间复杂度为O(logn)

所以,GetMedian()操作算法过程为:

  • 初始化一个大根堆,存中位数左边的数据,一个小根堆,存中位数右边的数据
  • 动态维护两个数据结构的大小,即最多只相差一个

代码

#include <queue>
class Solution {
private:#define SCD static_cast<double>priority_queue<int> min_q;priority_queue<int, vector<int>, greater<int>> max_q;public:void Insert(int num) {//优先插入到对应的大堆min_q.push(num);max_q.push(min_q.top());min_q.pop();if(min_q.size() < max_q.size()){min_q.push(max_q.top());max_q.pop();}        }double GetMedian() { //因为是优先插入大堆的, 所以:min_q >= max_qreturn min_q.size() > max_q.size() ? SCD(min_q.top()) : SCD(min_q.top() + max_q.top()) / 2;}};

复杂度

  • 时间复杂度:Insert函数O( l o g n logn logn),维护堆的复杂度,GetMedian函数O(1),直接访问
  • 空间复杂度:O(n),两个堆的空间,虽是两个,但是一个堆最多 n / 2 n / 2 n/2
http://www.lryc.cn/news/357510.html

相关文章:

  • JavaScript-JavaWeb
  • vue组件通讯$parent和$children获取单签组件的⽗组件和当前组件的⼦组件的例子
  • Util和utils
  • 拷贝构造、移动构造、拷贝赋值、移动赋值
  • Python3 笔记:math模块
  • python -【四】函数
  • 力扣 5. 最长回文子串 python AC
  • 【微机原理及接口技术】可编程计数器/定时器8253
  • 23种设计模式之一— — — —装饰模式详细介绍与讲解
  • 2024年2月28日 星期三
  • Java中的super关键字详解
  • 消消乐游戏开发,三消游戏,消除小游戏
  • 三十三、openlayers官网示例Drawing Features Style——在地图上绘制图形,并修改绘制过程中的颜色
  • Vue——事件修饰符
  • Go语言GoFly框架快速新增接口/上手写代码
  • 【Vue】v-else 和 v-else-if
  • 一致性hash算法原理图和负载均衡原理-urlhash与least_conn案例
  • MySQL建库
  • 系统资源监控器工具glances的使用详解
  • JDBC使用QreryRunner简化SQL查询注意事项
  • 前缀和(下)
  • 【排序算法】希尔排序
  • 数学建模--LaTex插入表格详细介绍
  • 未来已来:Flutter引领的安卓与跨平台开发奇幻之旅
  • 如何将Windows PC变成Wi-Fi热点?这里提供详细步骤
  • 报错:Cannot invoke “springfox.documentation.service.ParameterType.getIn()“
  • 一个生动的例子——通过ERC20接口访问Tether合约
  • 新媒体时代,LCD电子价签赋予零售场景新活力
  • 芋道源码 / yudao-cloud:前端技术架构探索与实践
  • 2024 angstromCTF re 部分wp