刷题笔记21——(暴力、大小堆)求数据流的中位数
时间:2019-01-18
本文章向大家介绍刷题笔记21——(暴力、大小堆)求数据流的中位数,主要包括刷题笔记21——(暴力、大小堆)求数据流的中位数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
解法1:暴力解
每进来一个都对它做排序,然后再求中位数
解法2:使用大小堆
这里使用STL中的优先队列,它底层是用堆实现的
测试结果及代码
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
void printArray(int a[], int N) {
for (int i = 0; i < N; ++i) {
cout << a[i] << " ";
}
// cout << endl;
}
void compare(vector<int> a) {
vector<int> t;
for (int i = 0; i < a.size(); ++i) {
t.push_back(a[i]);
sort(t.begin(), t.end());
cout << "\n当前序列:";
for (const auto &j : t) {
cout << j << " ";
}
double res = 0;
size_t sz = t.size();
cout << ",size为:" << sz;
if (sz % 2 == 1)
res = t[sz / 2];
else {
int left = sz / 2 - 1;
int right = sz / 2;
res = 0.5 * (t[left] + t[right]);
}
cout << ",中位数为:" << res << endl;
}
}
void printResult(const priority_queue<int, vector<int>, less<int>> &maxHeap,
const priority_queue<int, vector<int>, greater<int>> &minHeap) {
priority_queue<int, vector<int>, less<int>> tp = maxHeap;
priority_queue<int, vector<int>, greater<int>> tq = minHeap;
cout << "\n当前序列:";
vector<int> t;
while (!tq.empty()) {
t.push_back(tq.top());
tq.pop();
}
while (!tp.empty()) {
t.push_back(tp.top());
tp.pop();
}
sort(t.begin(), t.end());
auto it = t.begin();
while (it != t.end()) {
cout << *it << " ";
it++;
}
cout << ",size为:" << t.size();
t.clear();
}
void Insert(int num,
priority_queue<int, vector<int>, less<int>> &maxHeap,
priority_queue<int, vector<int>, greater<int>> &minHeap) {
// p是大根堆,q是小根堆
if (maxHeap.empty() || num <= maxHeap.top())
maxHeap.push(num);
else
minHeap.push(num);
if (maxHeap.size() == minHeap.size() + 2) {
minHeap.push(maxHeap.top());
maxHeap.pop();
}
if (minHeap.size() == maxHeap.size() + 2) {
maxHeap.push(minHeap.top());
minHeap.pop();
}
printResult(maxHeap, minHeap);
}
double getMedian(priority_queue<int, vector<int>, less<int>> &maxHeap,
priority_queue<int, vector<int>, greater<int>> &minHeap) {
int max_sz = maxHeap.size();
int min_sz = minHeap.size();
if (((max_sz + min_sz) & 1) == 0)
return 0.5 * (maxHeap.top() + minHeap.top());
if (max_sz > min_sz) {
return maxHeap.top();
}
return minHeap.top();
}
void test(vector<int> a) {
priority_queue<int, vector<int>, less<int>> maxHeap;
priority_queue<int, vector<int>, greater<int>> minHeap;
for (int i = 0; i < a.size(); ++i) {
Insert(a[i], maxHeap, minHeap);
cout << ",中位数为:" << getMedian(maxHeap, minHeap) << endl;
}
}
int main (int argc, char* argv[]) {
srand(time(NULL));
// const int size = 5; // 随机生成的数组大小
const int test_time = 120; // 测试次数
vector<int> a;
vector<int> tmp1;
vector<int> tmp2;
for (int cnt = 0; cnt < test_time; ++cnt) {
int N = rand() % 10 + 1;
cout << "\n第 " << cnt << " 次生成:";
for (int i = 0; i < N; ++i) {
a.push_back(rand() % 20 + 1);
cout << a[i] << " ";
}
cout << endl;
tmp1 = a;
tmp2 = a;
cout << "\n第 " << cnt << " 次对比:";
compare(tmp1);
// cout << "tmp1:";
// for (const auto &j : tmp1) {
// cout << j << " ";
// }
// cout << endl;
// cout << "tmp2:";
cout << "\n第 " << cnt << " 次测试:";
test(tmp2);
// for (const auto &k : tmp2) {
// cout << k << " ";
// }
cout << endl;
a.clear();
tmp1.clear();
tmp2.clear();
}
return 0;
}
- ADO.NET入门教程(八) 深入理解DataAdapter(上)
- 深入理解DIP、IoC、DI以及IoC容器
- C#委托使用详解(Delegates)
- LINC switch系列之安装指南
- 设计模式成长记(一) 抽象工厂模式(Abstract Factory)
- 基于Open vSwitch的VxLAN隧道实验网络
- 来来来,快来围观那个Kotlin
- 怎样提高网站访问速度缩短网页加载时间
- 使用Kotlin开发一个Spring Boot Webflux Streaming应用(附视频)
- 插入排序算法
- Javascript 的addEventListener()及attachEvent()区别分析
- 设计模式-用接口来实现filter!梭梭就是干!
- OpenDaylight实现轮询策略的负载均衡服务
- 微服务业务开发三个难题-拆分、事务、查询(上)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JavaWeb——MyBatis框架之连接池原理、MyBatis事务提交设置、动态SQL语法总结
- 8种ETL算法归纳总结,看完这些你就全明白了
- JavaWeb——Maven基础之详细总结,从零开始搭建Maven工程,包含一些常见的坑org.eclipse.jdt.internal.compiler.classfmt.ClassFormatEx
- JavaWeb——Redis数据库之Jedis操作5种类型数据的使用总结与前端Ajax获取Redis缓存数据的案例实战(结合了MySQL数据库)
- Java——数据库编程JDBC之快速入门吐血总结及各关键对象详解(提供了JDBCUtils工具类)
- MySQL数据库——事务的操作(开启、回滚、提交)、特征、隔离级别基础总结
- MySQL数据库——数据库的设计(多表之间的关系与三大范式)与备份还原
- JavaWeb——JSP入门学习(JSP基本概念、JSP脚本、JSP内置对象)
- MySQL数据库——数据库CRUD之基本DML增删改表操作及DQL查表操作
- JavaWeb——AJAX异步技术实现方式与案例实战(原生的JS方式、使用JQuery方式)
- JavaWeb——一文带你入门Servlet(生命周期、注解配置方法、IDEA与tomcat的相关配置)
- JavaWeb——JQuery之基础案例实战(实现表格隔行换色、实现全选全不选、QQ表情选择、下拉列表选中条目左右选择功能)
- JavaWeb——JQuery之DOM操作应用及实践案例总结(DOM内容操作、DOM属性操作、CRUD操作)
- JavaWeb——Filter过滤器快速入门与是否登录验证&过滤敏感词汇案例实战(Filter配置方式、执行流程、生命周期方法、过滤器链)
- JavaWeb——会话技术之Session快速入门与验证码登录案例实战(Session实现原理、使用细节、快速入门、Session的特点)