295. Find Median from Data Stream

  • 题目思路

  • 代码实现

  • 1 code1
class MedianFinder
{
public:
	/** initialize your data structure here. */
	MedianFinder()
	{
		maxheapsize = 0;
		minheapsize = 0;
	}

	void addNum(int num)
	{
		//1 和大根堆的堆顶元素进行比较
		//比大根堆的堆顶元素大--->将元素插入的小根堆--->插入过程发现heapsize的差大于1--->小根堆弹出堆顶元素给大根堆,小根堆插入新元素
		//比大根堆的堆顶元素小--->将元素插入到大根堆--->插入过程发现heapsize的差大于1--->大根堆弹出堆顶元素给小根堆,大根堆插入新元素
		if (maxheapsize == 0)
		{
			maxheap.push_back(num);
			make_heap(maxheap.begin(), maxheap.end());
			maxheapsize++;
		}
		else
		{
			if (num > maxheap[0])  //num 比大根堆的堆顶大
			{

				if (minheapsize + 1 - maxheapsize > 1)
				{
					//先弹出 在插入
					pop_heap(minheap.begin(), minheap.end(), std::greater<>{});
					auto smallest = minheap.back();
					minheap.pop_back();
					minheapsize--;

					//最大堆插入
					maxheap.push_back(smallest);
					push_heap(maxheap.begin(), maxheap.end());
					maxheapsize++;

					//最小堆插入
					minheap.push_back(num);
					push_heap(minheap.begin(), minheap.end(), std::greater<>{});
					minheapsize++;
				}
				else
				{
					//将元素插入的小根堆
					minheap.push_back(num);
					push_heap(minheap.begin(), minheap.end(), std::greater<>{});
					minheapsize++;
				}
			}
			else  // num <= 大根堆的堆顶
			{
				if (maxheapsize + 1 - minheapsize > 1)
				{
					//大根堆弹出堆顶元素给小根堆,大根堆插入新元素
					//先弹出 在插入
					pop_heap(maxheap.begin(), maxheap.end());
					auto largest = maxheap.back();
					maxheap.pop_back();
					maxheapsize--;

					//最小堆插入
					minheap.push_back(largest);
					push_heap(minheap.begin(), minheap.end(), std::greater<>{});
					minheapsize++;

					//最大堆插入
					maxheap.push_back(num);
					push_heap(maxheap.begin(), maxheap.end());
					maxheapsize++;
				}
				else
				{
					//将元素插入大根堆
					maxheap.push_back(num);
					push_heap(maxheap.begin(), maxheap.end());
					maxheapsize++;
				}
			}
		}


	}  //end void addNum(int num) 

	double findMedian()
	{
		if (maxheapsize == 1 && minheapsize == 0)
		{
			return maxheap[0];
		}
		if ((maxheapsize + minheapsize) % 2 == 0)
		{
			//当前两个堆中的元素共偶数个
			return double(maxheap[0] + minheap[0]) / 2;
		}
		else
		{
			return minheap[0];
		}
	}
private:
	vector<int> maxheap;  //大根堆
	vector<int> minheap;  //小根堆
	int maxheapsize;
	int minheapsize;

};
  • 2 code2
class MedianFinder
{
public:
	/** initialize your data structure here. */
	MedianFinder()
	{
		maxheapsize = 0;
		minheapsize = 0;
	}

	void addNum(int num)
	{	
		if (minheapsize == 0)
		{
			minheap.push_back(num);
			make_heap(minheap.begin(), minheap.end(), std::greater<>{});
			minheapsize++;
		}
		else
		{
			if (num <= minheap[0])  //num <= 小根堆的堆顶
			{
                //应该插入大根堆 下面就插入大根堆的情况进行讨论

				if (maxheapsize + 1 - minheapsize > 1)
				{
					//大根堆弹出堆顶元素给小根堆,大根堆插入新元素
                    
					//先弹出 在插入
					pop_heap(maxheap.begin(), maxheap.end());
					auto largest = maxheap.back();
					maxheap.pop_back();
					maxheapsize--;

					//最小堆插入
					minheap.push_back(largest);
					push_heap(minheap.begin(), minheap.end(), std::greater<>{});
					minheapsize++;

					//最大堆插入
					maxheap.push_back(num);
					push_heap(maxheap.begin(), maxheap.end());
					maxheapsize++;

				}
				else
				{
					//直接插入大根堆
					maxheap.push_back(num);
					push_heap(maxheap.begin(), maxheap.end());
					maxheapsize++;
				}

			}
			else  // num > 小根堆的堆顶
			{
				//应该插入小根堆 下面就插入小根堆的情况进行讨论

				if (minheapsize + 1 - maxheapsize > 1)
				{
					//先弹出 在插入
					pop_heap(minheap.begin(), minheap.end(), std::greater<>{});
					auto smallest = minheap.back();
					minheap.pop_back();
					minheapsize--;

					//最大堆插入
					maxheap.push_back(smallest);
					push_heap(maxheap.begin(), maxheap.end());
					maxheapsize++;

					//最小堆插入
					minheap.push_back(num);
					push_heap(minheap.begin(), minheap.end(), std::greater<>{});
					minheapsize++;
				}
				else
				{
					//直接插入小根堆
					minheap.push_back(num);
					push_heap(minheap.begin(), minheap.end(), std::greater<>{});
					minheapsize++;
				}
			}
		}
	}  //end void addNum(int num) 

	double findMedian()
	{
		if (minheapsize == 1 && maxheapsize == 0)
		{
			return minheap[0];
		}

		if ((maxheapsize + minheapsize) % 2 == 0)
		{
			return double(maxheap[0] + minheap[0]) / 2;
		}
		else  //奇数个
		{
			return maxheap[0];
		}
	}
private:
	vector<int> maxheap;  //大根堆
	vector<int> minheap;  //小根堆
	int maxheapsize;
	int minheapsize;

};

code2对于递增序列,如{1,2,3,4,5}输出的值不正确。
code1和code2都是有问题的代码,稍后将正确代码上传。

  • 正确的代码

code1和code2使用递减序列和递增序列就能测出来代码有问题,去网上参考了一下其他人的代码,正确代码如下:

class MedianFinder
{
public:
	MedianFinder()
	{

	}
	void addNum(int num)
	{
		if (l_.empty() || num <= l_.top())
		{
			l_.push(num);
		}
		else
		{
			r_.push(num);
		}

		//step2
		if (l_.size() < r_.size())
		{
			l_.push(r_.top());
			r_.pop();
		}
		else if (l_.size() - r_.size() == 2)
		{
			r_.push(l_.top());
			l_.pop();
		}
	}
	double findMedian()
	{
		if (l_.size() > r_.size())
		{
			return static_cast<double>(l_.top());
		}
		else
		{
			return (static_cast<double>( l_.top() + r_.top() )) / 2;
		}
	}
private:
	priority_queue<int, vector<int>, less<int>> l_;
	priority_queue<int, vector<int>, greater<int>> r_;
};
原文地址:https://www.cnblogs.com/Manual-Linux/p/12027821.html