首页 > 编程语言 >C++算法:数据流的中位数

C++算法:数据流的中位数

时间:2023-10-24 16:03:47浏览次数:40  
标签:set 中位数 C++ addNum qTopMax iNum 数据流 MedianFinder size


题目

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
例如 arr = [2,3,4] 的中位数是 3 。
例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类:
MedianFinder() 初始化 MedianFinder 对象。
void addNum(int num) 将数据流中的整数 num 添加到数据结构中。
double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。
示例 1:
输入
[“MedianFinder”, “addNum”, “addNum”, “findMedian”, “addNum”, “findMedian”]
[[], [1], [2], [], [3], []]
输出
[null, null, null, 1.5, null, 2.0]
解释
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1); // arr = [1]
medianFinder.addNum(2); // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3); // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0
提示:
-105 <= num <= 105
在调用 findMedian 之前,数据结构中至少有一个元素
最多 5 * 104 次调用 addNum 和 findMedian

2023年5月版

有的优先队列(堆)
 class MedianFinder {
 public:
 MedianFinder() {
 }
 void addNum(int num) {
 m_qTopMax.emplace(num);
 if (m_qTopMax.size() > m_qTopMin.size() + 1)
 {
 auto tmp = m_qTopMax.top();
 m_qTopMax.pop();
 m_qTopMin.emplace(tmp);
 }
 if (m_qTopMax.size() && m_qTopMin.size())
 {
 const int iTopMax = m_qTopMax.top();
 const int iTopMin = m_qTopMin.top();
 if (iTopMax > iTopMin)
 {
 m_qTopMax.pop();
 m_qTopMin.pop();
 m_qTopMax.push(iTopMin);
 m_qTopMin.push(iTopMax);
 }
 }
 }
 double findMedian() {
 if (m_qTopMax.size() == m_qTopMin.size())
 {
 return (m_qTopMax.top() + m_qTopMin.top()) / 2.0;
 }
 return m_qTopMax.top();
 }
 std::priority_queue m_qTopMax;
 std::priority_queue<int,std::vector,std::greater> m_qTopMin;
 };

8月第一版

用的可重复集合

class MedianFinder {
 public:
 MedianFinder() {
 }
 void addNum(int num) {
 m_set.emplace(num);
 if (1 == m_set.size())
 {
 m_it = m_set.begin();
 }
 if (num < *m_it)
 {
 m_iNum++;
 }
 while (m_iNum < m_set.size() / 2)
 {
 m_it++;
 m_iNum++;
 }
 while (m_iNum > m_set.size() / 2)
 {
 m_it–;
 m_iNum–;
 }
 }
 double findMedian() {
 if (1 & m_set.size())
 {
 return *m_it;
 }
 auto tmp = m_it;
 –tmp;
 return (*tmp + *m_it) / 2.0;
 }
 multiset m_set;
 multiset::iterator m_it = m_set.begin();
 int m_iNum = 0;//[m_set.begin(),m_it)的元素个数
 };

优化版

减少集合数

class MedianFinder {
 public:
 MedianFinder() {
 }
 void addNum(int num) {
 m_set.emplace(num);
 if (m_set.end() == m_it )
 {
 m_it = m_set.begin();
 return ;
 }
 if (num < *m_it)
 {
 m_iNum++;
 }
 while (m_iNum < m_set.size() / 2)
 {
 m_it++;
 m_iNum++;
 }
 while (m_iNum > m_set.size() / 2)
 {
 m_it–;
 m_iNum–;
 }
 }
 double findMedian() {
 if (1 & m_set.size())
 {
 return *m_it;
 }
 auto tmp = m_it;
 –tmp;
 return (*tmp + *m_it) / 2.0;
 }
 multiset m_set;
 multiset::iterator m_it = m_set.begin();
 int m_iNum = 0;//[m_set.begin(),m_it)的元素个数
 };

扩展阅读


相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版

| 鄙人想对大家说的话
|
|-|
|闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。|
| 墨家名称的来源:有所得以墨记之。 |
|如果程序是一条龙,那算法就是他的是睛|

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境:

VS2022 C++17

C++算法:数据流的中位数_优先队列


标签:set,中位数,C++,addNum,qTopMax,iNum,数据流,MedianFinder,size
From: https://blog.51cto.com/u_15724537/8005219

相关文章

  • C++算法前缀和的应用:分割数组的最大值的原理、源码及测试用例
    分割数组的最大值二分过些天整理基础知识题目给定一个非负整数数组nums和一个整数m,你需要将这个数组分成m个非空的连续子数组。设计一个算法使得这m个子数组各自和的最大值最小。示例1:输入:nums=[7,2,5,10,8],m=2输出:18解释:一共有四种方法将nums分割为2个......
  • C++算法:给表达式添加运算符
    题目给定一个仅包含数字0-9的字符串num和一个目标值整数target,在num的数字之间添加二元运算符(不是一元)+、-或*,返回所有能够得到target的表达式。注意,返回表达式中的操作数不应该包含前导零。示例1:输入:num=“123”,target=6输出:[“1+2+3”,“123......
  • C++数位算法:数字1的个数
    题目给定一个整数n,计算所有小于等于n的非负整数中数字1出现的个数。示例1:输入:n=13输出:6示例2:输入:n=0输出:0提示:0<=n<=1092023年1月版classSolution{public:intcountDigitOne(intn){intiNum=0;intiMul=1;for(inti=0;i<9;i++){......
  • C++桶排序算法的应用:存在重复元素 III
    题目给你一个整数数组nums和两个整数indexDiff和valueDiff。找出满足下述条件的下标对(i,j):i!=j,abs(i-j)<=indexDiffabs(nums[i]-nums[j])<=valueDiff如果存在,返回true;否则,返回false。示例1:输入:nums=[1,2,3,1],indexDiff=3,valueDiff=0输出......
  • C++前缀和算法应用:矩形区域不超过 K 的最大数值和
    题目给你一个mxn的矩阵matrix和一个整数k,找出并返回矩阵内部矩形区域的不超过k的最大数值和。题目数据保证总会存在一个数值和不超过k的矩形区域。示例1:输入:matrix=[[1,0,1],[0,-2,3]],k=2输出:2解释:蓝色边框圈出来的矩形区域[[0,1],[-2,3]]的数值和是......
  • 时间复杂度O(40n*n)的C++算法:修改图中的边权
    1.12.1.题目给你一个n个节点的无向带权连通图,节点编号为0到n-1,再给你一个整数数组edges,其中edges[i]=[ai,bi,wi]表示节点ai和bi之间有一条边权为wi的边。部分边的边权为-1(wi=-1),其他边的边权都为正数(wi>0)。你需要将所有边权为-1的边都修改为范......
  • 在C++中,互斥变量(std::mutex)是用于保护共享资源的重要工具,但它们确实有一些局限性,其中
    在C++中,互斥变量(std::mutex)是用于保护共享资源的重要工具,但它们确实有一些局限性,其中之一是无法保证包含指针的区域的多线程安全。这是因为互斥锁本质上只能保护它们所保护的代码块,而不会考虑指针指向的数据。下面是一些与互斥锁和指针相关的常见问题和注意事项:共享数据的复制:......
  • C++_Cmake的使用
    C++系统版本、软件依赖版本、组件LSB(全称:LinuxStandardsBase)LSBsharedobjectELF是ExecutableLinkableFormat的缩写,是Linux的链接、可执行、共享库的格式标准,COFF:CommonObjectCOFF(通用对象文件格式) 编译器:简单构建gcc编译流程分为4个步骤,分......
  • C++初识(续篇)
    1.2注释作用:在代码中加一些说明和解释,方便自己或其他程序员阅读代码两中格式单行注释:通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明//这样的是单行注释多行注释:通常放在一段代码的上方,对该段代码做整体说明/*这种的是多行注释可以写好多行*/......
  • c++中的宏#define用途
    宏的一些作用,包括但不限于这些定义一个变量、字符串、类型定义一个函数、条件表达式条件编译、调试信息,异常类定义结构体、命名空间定义模版、枚举、函数对象#define宏定义在C++中用于定义常量、函数、条件编译、字符串、条件表达式、变量、注释、调试信息、类型、函数等,下面是一些......