LeetCode295. Find Median from Data Stream(剑指offer41题)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_41042404/article/details/88564743

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

For example,
[2,3,4], the median is 3

[2,3], the median is (2 + 3) / 2 = 2.5

Design a data structure that supports the following two operations:

void addNum(int num) - Add a integer number from the data stream to the data structure.
double findMedian() - Return the median of all elements so far.

Example:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

Follow up:

If all integer numbers from the stream are between 0 and 100, how would you optimize it?
If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?

法一

开两个stl的优先队列-maxheap。small放前一半大的数,large放后一半大的数。
为了让他们的顺序从小到大不变,small的用原数存,large的用负数存。
增删O(logn),查找O(1)
细节:
1.如果是奇数大小,small.top()就是要求的中位数。如果是偶数,(small.top()-large.top())/2就是中位数,是减不是加
2.优先队列的类型是long. -2^31 (which negated is itself, when using 32-bit ints), I use integer types larger than 32 bits.
3.(small.top()-large.top())/2.0。要除以2.0,否则返回的是整数

class MedianFinder {
private:
 std::priority_queue<long> small,large;
    
public:
    /** initialize your data structure here. */
    MedianFinder() {
          }
    
    void addNum(int num) {
        small.push(num);//O(logn)

        large.push(-small.top());//O(logn)
        small.pop();//O(logn)

        //保证small大于或者等于large的个数
        if(small.size()<large.size())
        {
            small.push(-large.top());
            large.pop();
        }
    }
    
    double findMedian() {
        return small.size()>large.size()? small.top():(small.top()-large.top())/2.0;
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

法2

开两个stl的优先队列-maxheap和minheap,用来存前后一半的数
细节:
1.如果num小于maxheap.top(),说明在num小的那一半里,放入最大堆,如果不这样的话,可能会排序失败。
2.假定maxheap永远大于或者等于minheap的数量,这样如果两个堆相等就是平均值。不相等就是maxheap.top
3.利用AVL的思想,保证两个堆的深度之差不超过1,如果超过1,就把max堆顶放入min堆中

class MedianFinder {
private:
	priority_queue<long> maxheap;
	priority_queue<long, vector<long>, greater<long>> minheap;

public:
	/** initialize your data structure here. */
	MedianFinder() {
	}

	void addNum(int num) {
		//细节:如果num小于maxheap.top(),说明在num小的那一半里,放入最大堆,如果不这样的话,可能会排序失败。
		if (maxheap.size() == 0 || num < maxheap.top())
		{
			maxheap.push(num);
		}
		else
			minheap.push(num);
		//平衡二叉树
        if (minheap.size()> maxheap.size())
		{
			maxheap.push(minheap.top());
			minheap.pop();
		}
        else if (maxheap.size()>1 + minheap.size())
		{
			minheap.push(maxheap.top());
			maxheap.pop();
		}  
	}

	double findMedian() {
		return maxheap.size()>minheap.size() ? maxheap.top() : (maxheap.top() + minheap.top()) / 2.0;
	}
};
展开阅读全文

data io stream 的问题

12-18

import java.io.*;rnrnpublic class DataIODemo rn public static void main(String[] args) throws IOException rnrn // write the data outrn DataOutputStream out = new DataOutputStream(newrn FileOutputStream("invoice1.txt"));rnrn double[] prices = 19.99, 9.99, 15.99, 3.99, 4.99 ;rn int[] units = 12, 8, 13, 29, 50 ;rn String[] descs = "Java T-shirt",rn "Java Mug",rn "Duke Juggling Dolls",rn "Java Pin",rn "Java Key Chain" ;rn rn for (int i = 0; i < prices.length; i ++) rn out.writeDouble(prices[i]);rn out.writeChar('\t');rn out.writeInt(units[i]);rn out.writeChar('\t');rn out.writeChars(descs[i]);rn out.writeChar('\n');rn rn out.close();rnrn // read it in againrn DataInputStream in = new DataInputStream(newrn FileInputStream("invoice1.txt"));rnrn double price;rn int unit;rn StringBuffer desc;rn double total = 0.0;rnrn try rn while (true) rn price = in.readDouble();rn in.readChar(); // throws out the tabrn unit = in.readInt();rn in.readChar(); // throws out the tabrn char chr;rn desc = new StringBuffer(50);rn char lineSep = System.getProperty("line.separator").charAt(0);rn while ((chr = in.readChar()) != lineSep)rn desc.append(chr);rn System.out.println("You've ordered " +rn unit + " units of " +rn desc + " at $" + price);rn total = total + unit * price;rn rn catch (EOFException e) rn rn System.out.println("For a TOTAL of: $" + total);rn in.close();rn rnrnrn上面折断程序的执行结果应该是rnYou've ordered 12 units of Java T-shirt at $19.99rnYou've ordered 8 units of Java Mug at $9.99rnYou've ordered 13 units of Duke Juggling Dolls at $15.99rnYou've ordered 29 units of Java Pin at $3.99rnYou've ordered 50 units of Java Key Chain at $4.99rnFor a TOTAL of: $892.8800000000001rnrn可是在我的机器上执行的结果却是rnYou've ordered 12 units of Java T-shirtrn???? Java Mugrn???? at $19.99rnFor a TOTAL of: $239.88rnrn我的系统是中文win98,不知道是不是和中文系统有关系,是不是在英文系统下能成功执行?各位有遇到过相同的情况的吗?怎么解决呢?谢谢。 论坛

data io stream 问题

12-19

import java.io.*;rnrnpublic class DataIODemo rn public static void main(String[] args) throws IOException rnrn // write the data outrn DataOutputStream out = new DataOutputStream(newrn FileOutputStream("invoice1.txt"));rnrn double[] prices = 19.99, 9.99, 15.99, 3.99, 4.99 ;rn int[] units = 12, 8, 13, 29, 50 ;rn String[] descs = "Java T-shirt",rn "Java Mug",rn "Duke Juggling Dolls",rn "Java Pin",rn "Java Key Chain" ;rn rn for (int i = 0; i < prices.length; i ++) rn out.writeDouble(prices[i]);rn out.writeChar('\t');rn out.writeInt(units[i]);rn out.writeChar('\t');rn out.writeChars(descs[i]);rn out.writeChar('\n');rn rn out.close();rnrn // read it in againrn DataInputStream in = new DataInputStream(newrn FileInputStream("invoice1.txt"));rnrn double price;rn int unit;rn StringBuffer desc;rn double total = 0.0;rnrn try rn while (true) rn price = in.readDouble();rn in.readChar(); // throws out the tabrn unit = in.readInt();rn in.readChar(); // throws out the tabrn char chr;rn desc = new StringBuffer(50);rn char lineSep = System.getProperty("line.separator").charAt(0);rn while ((chr = in.readChar()) != lineSep)rn desc.append(chr);rn System.out.println("You've ordered " +rn unit + " units of " +rn desc + " at $" + price);rn total = total + unit * price;rn rn catch (EOFException e) rn rn System.out.println("For a TOTAL of: $" + total);rn in.close();rn rnrnrn上面折断程序的执行结果应该是rnYou've ordered 12 units of Java T-shirt at $19.99rnYou've ordered 8 units of Java Mug at $9.99rnYou've ordered 13 units of Duke Juggling Dolls at $15.99rnYou've ordered 29 units of Java Pin at $3.99rnYou've ordered 50 units of Java Key Chain at $4.99rnFor a TOTAL of: $892.8800000000001rnrn可是在我的机器上执行的结果却是rnYou've ordered 12 units of Java T-shirtrn???? Java Mugrn???? at $19.99rnFor a TOTAL of: $239.88rnrn我的系统是中文win98,不知道是不是和中文系统有关系,是不是在英文系统下能成功执行?各位有遇到过相同的情况的吗?怎么解决呢?谢谢。 论坛

没有更多推荐了,返回首页