剑指offer——Day17 排序(中等)

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)函数:

  1. 当 m=n(即 N 为 偶数):需向 A 添加一个元素。实现方法:将新元素 num 插入至 B ,再将 B 堆顶元素插入至 A ;
  2. 当 m≠n(即 N 为 奇数):需向 B 添加一个元素。实现方法:将新元素 num 插入至 A ,再将 A 堆顶元素插入至 B ;

findMedian()函数

  1. 当 m=n( N 为 偶数):则中位数为 (A 的堆顶元素 + B 的堆顶元素 )/2。
  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;
    }
}

代码表现

posted @ 2023-02-01 13:43  神鹏佐佑  阅读(17)  评论(0)    收藏  举报