小学生都能看懂的题解 | #数据流中的中位数#
数据流中的中位数
https://www.nowcoder.com/practice/9be0172896bd43948f8a32fb954e1be1
问题是什么?
我们需要一个程序,这个程序可以从一个数据流里不断地读取数字,并且能随时告诉我们这些数字的“中间数”(也就是中位数)。如果数字的总数是奇数,中位数就是正中间的那个数;如果是偶数,中位数就是中间两个数的平均值。
我们怎么解决?
我们可以想象有两个队伍,一个是“小队”,一个是“大队”。每次新来一个数字,我们就把它放到合适的队伍里。“小队”总是放更小的数,“大队”放更大的数。但是,这两个队伍的人数不能差太多,最多只能差一个人。
具体怎么做?
- 创建两个队伍:
- “小队”用一个叫做 maxHeap 的特殊队伍,它总是让最大的数站在最前面。
- “大队”用一个叫做 minHeap 的特殊队伍,它总是让最小的数站在最前面。
- 每次有新数字来的时候:
- 如果这个数字比“小队”的队长还小,或者“小队”是空的,就把它加到“小队”里。
- 否则,把它加到“大队”里。
- 保持队伍人数接近:
- 如果“小队”的人数比“大队”多两个人以上,就把“小队”的队长送到“大队”去。
- 如果“大队”的人数比“小队”多,就把“大队”的队长送到“小队”去。
- 找出中位数:
- 如果两个队伍人数一样,中位数就是两个队长的平均值。
- 如果“小队”的人数比“大队”多一个,中位数就是“小队”的队长。
实现代码:
下面的代码实现了上面说的功能,使用了 Java 的 PriorityQueue(优先队列),来帮助我们管理这两个特殊的队伍。
import java.util.PriorityQueue; public class MedianFinder { private PriorityQueue<Integer> smallTeam; // 小队,保存较小的数 private PriorityQueue<Integer> bigTeam; // 大队,保存较大的数 public MedianFinder() { smallTeam = new PriorityQueue<>((a, b) -> b - a); // 小队,让大的数排前面 bigTeam = new PriorityQueue<>(); // 大队,让小的数排前面 } // 插入新数字的方法 public void Insert(Integer val) { if (smallTeam.isEmpty() || val <= smallTeam.peek()) { smallTeam.add(val); } else { bigTeam.add(val); } // 保持队伍人数接近 if (smallTeam.size() > bigTeam.size() + 1) { bigTeam.add(smallTeam.poll()); } else if (bigTeam.size() > smallTeam.size()) { smallTeam.add(bigTeam.poll()); } } // 获取中位数的方法 public Double GetMedian() { if (smallTeam.size() == bigTeam.size()) { return (smallTeam.peek() + bigTeam.peek()) / 2.0; } else { return (double)smallTeam.peek(); } } }
这个代码会把新来的数字放进合适的队伍,并且随时调整队伍,确保我们总能找到正确的中位数。
如果这篇文章对你有帮助,请点个免费的赞👍,让它能够帮助更多的人。
#牛客创作赏金赛#小学生都能看懂的算法 文章被收录于专栏
主要面向小白的算法文章。以小学生都能看懂为目标而编写,顺便巩固下自己。