CI20.9--中位数问题

本文介绍了一种高效算法,用于动态维护一组数值的中位数。通过使用两个堆(一个最大堆和一个最小堆),该算法能在新增数值时快速调整以保持中位数的准确性。这种方法特别适用于数据流场景,其复杂度为插入O(logn)和获取中位数O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

随机生成一些数,写一个程序找到这些数的中位数,并且当新的数生成的时候能够维护中位数。

思路:

直观的思路是排序或者用划分的思路找中位数,但是这些都是在数组固定的情况下,现在的情况是随时可能有新的数产生。

1、可以用一个足够大的数组来维护这些数,然后每产生一个数就将它插入到数组中并保持有序,这样插入一个数的复杂度为O(n),取中位数的复杂度为O(1)。

2、可以用一个堆来位数这些数,插入一个数的复杂度为O(logn),但取中位数要先堆排序,复杂度为O(nlogn)。

3、可以用一个大顶堆maxheap和一个小顶堆minheap来维护中位数。大顶堆存放小于等于中位数的数,小顶堆存放大于等于中位数的数。在插入的时候随时保持 maxheap.size() == minheap.size() 或 maxheap.size() == minheap.size() + 1,这样中位数的值为 (maxheap.top() + minheap.top())/2 或 maxheap.top(),即取中位数的复杂度为O(1)。

#include <iostream>
#include <queue>
#include <assert.h>
#include <time.h>
using namespace std;

class CMedian
{
public:
	void Insert(int v);
	int GetMedian();
private:
	priority_queue<int> max;
	priority_queue< int, vector<int>, greater<int> > min;
};

void CMedian::Insert(int num)
{
	if (max.size() == min.size())
	{
		if (max.empty())
			max.push(num);
		else
		{
			if (num <= min.top())
				max.push(num);
			else
			{
				max.push(min.top());
				min.pop();
				min.push(num);
			}
		}
	}
	else
	{
		if (num >= max.top())
			min.push(num);
		else
		{
			min.push(max.top());
			max.pop();
			max.push(num);
		}
	}
}

int CMedian::GetMedian()
{
	assert(!max.empty());
	if (max.size() == min.size())
		return max.top() + ((min.top() - max.top()) >> 1);
	else
		return max.top();
}

int main()
{
	srand((unsigned)time(0));
	CMedian m;
	vector<int> ivec;
	int num = rand() % 50;
	for (int i = 0; i < num; ++i)
	{
		int value = rand() % 1000;
		ivec.push_back(value);
		m.Insert(value);
	}
	sort(ivec.begin(), ivec.end());
	for (int i = 0; i < ivec.size(); ++i)
		cout << ivec[i] << endl;
	cout << ivec[(num-1)/2] << " " << ivec[num/2] << endl;
	cout << m.GetMedian() << endl;
	return 0;
}

D题 天然肠衣搭配问题 天然肠衣(以下简称肠衣)制作加工是我国的一个传统产业,出口量占世界首位。肠衣经过清洗整理后被分割成长度不等的小段(原料),进入组装工序。传统的生产方式依靠人工,边丈量原料长度边心算,将原材料按指定根数和总长度组装出成品(捆)。 原料按长度分档,通常以0.5米为一档,如:3-3.4米按3米计算,3.5米-3.9米按3.5米计算,其余的依此类推。表1是几种常见成品 的规格,长度单位为米,∞表示没有上限,但实际长度小于26米。 表1 成品规格表 最短长度 最大长度 根数 总长度 3 6.5 20 89 7 13.5 8 89 14 ∞ 5 89 为了提高生产效率,公司计划改变组装工艺,先丈量所有原料,建立一个原料表。表2为某批次原料描述。 表2 原料描述表 长度 3-3.4 3.5-3.9 4-4.4 4.5-4.9 5-5.4 5.5-5.9 6-6.4 6.5-6.9 根数 43 59 39 41 27 28 34 21 长度 7-7.4 7.5-7.9 8-8.4 8.5-8.9 9-9.4 9.5-9.9 10-10.4 10.5-10.9 根数 24 24 20 25 21 23 21 18 长度 11-11.4 11.5-11.9 12-12.4 12.5-12.9 13-13.4 13.5-13.9 14-14.4 14.5-14.9 根数 31 23 22 59 18 25 35 29 长度 15-15.4 15.5-15.9 16-16.4 16.5-16.9 17-17.4 17.5-17.9 18-18.4 18.5-18.9 根数 30 42 28 42 45 49 50 64 长度 19-19.4 19.5-19.9 20-20.4 20.5-20.9 21-21.4 21.5-21.9 22-22.4 22.5-22.9 根数 52 63 49 35 27 16 12 2 长度 23-23.4 23.5-23.9 24-24.4 24.5-24.9 25-25.4 25.5-25.9 根数 0 6 0 0 0 1 根据以上成品和原料描述,设计一个原料搭配方案,工人根据这个方案“照方抓药”进行生产。 公司对搭配方案有以下具体要: (1) 对于给定的一批原料,装出的成品捆数越多越好; (2) 对于成品捆数相同的方案,最短长度最长的成品越多,方案越好; (3) 为提高原料使用率,总长度允许有± 0.5米的误差,总根数允许比标准少1根; (4) 某种规格对应原料如果出现剩余,可以降级使用。如长度为14米的原料可以和长度介于7-13.5米的进行捆扎,成品属于7-13.5米的规格; (5) 为了食品保鲜,要在30分钟内产生方案。 请建立上述问题的数学模型,给出解方法,并对表1、表2给出的实际数据进行解,给出搭配方案。给我解的MATLAB代码
最新发布
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值