Day17 2023.2.1 排序(中等)
40. 最小的k个数
自己实现
直接用了排序的函数,这个没啥好说的
代码表现
没有进行优化,中规中矩
41. 数据流中的中位数
自己实现
自己尝试用了最朴素的排序算法,但是超过了时间限制
代码如下:
class MedianFinder {
vector<int> res;
public:
/** initialize your data structure here. */
MedianFinder() {
}
void addNum(int num) {
res.push_back(num);
}
double findMedian() {
sort(res.begin(),res.end());
int len=res.size();
int mid=len/2;
if(len%2==1){
return (double)res[mid];
}
else{
int sum=res[mid]+res[mid-1];
return (double)sum/2.0;
}
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/
题解
通过堆能很好地优化时间复杂度
建立一个 小顶堆 A 和 大顶堆 B ,各保存列表的一半元素,且规定:
- A 保存 较大 的一半,长度为 N/2( N 为偶数)或 (N+1)/2( N 为奇数);
- B 保存 较小 的一半,长度为 N/2( N 为偶数)或 (N-1)/2( N 为奇数);
随后,中位数可仅根据 A,BA, BA,B 的堆顶元素计算得到。
设元素总数为 N=m+n ,其中 m 和 n 分别为 A 和 B 中的元素个数。
addNum(num)
函数:
- 当 m=n(即 N 为 偶数):需向 A 添加一个元素。实现方法:将新元素 num 插入至 B ,再将 B 堆顶元素插入至 A ;
- 当 m≠n(即 N 为 奇数):需向 B 添加一个元素。实现方法:将新元素 num 插入至 A ,再将 A 堆顶元素插入至 B ;
findMedian()
函数
- 当 m=n( N 为 偶数):则中位数为 (A 的堆顶元素 + B 的堆顶元素 )/2。
- 当 m≠n( N 为 奇数):则中位数为 A 的堆顶元素。
(由于这里面用到的堆在C++不太好实现,因此直接用Java体现思路)
代码如下:
class MedianFinder {
Queue<Integer> A, B;
public MedianFinder() {
A = new PriorityQueue<>(); // 小顶堆,保存较大的一半
B = new PriorityQueue<>((x, y) -> (y - x)); // 大顶堆,保存较小的一半
}
public void addNum(int num) {
if(A.size() != B.size()) {
A.add(num);
B.add(A.poll());
} else {
B.add(num);
A.add(B.poll());
}
}
public double findMedian() {
return A.size()!=B.size() ? A.peek() : (A.peek()+B.peek())/2.0;
}
}