0
点赞
收藏
分享

微信扫一扫

4月14日 剑指 Offer 41. 数据流中的中位数 剑指 Offer 43. 1~n 整数中 1 出现的次数

AbrahamW 2022-04-14 阅读 112

剑指 Offer 41. 数据流中的中位数

1、题目

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

在这里插入图片描述

2、题解

一、使用一个 list 集合即可
这里直接根据 list 中的元素排序,然后取中间元素即可。

二、双堆
根据堆的性质,可以判断两个堆的值从下往上递增,即:
bigHeap堆底 <= bigHeap堆顶 <= smallHeap 堆顶 <= smallHeap 堆底
在这里插入图片描述
将获取中位数的情况分为两类:

  1. 数据流为奇数时,保证两个堆的长度相差1,那么长度较大的堆的堆顶就是中位数;
  2. 数据流为偶数时,保证两个堆的长度相等,两个堆的堆顶相加除二就是中位数。

我们要保证每次插入元素后,两堆维持相对长度。让smallHeap 为长度较大的堆,每次插入元素时进行判断:

  • 当两堆总长度为偶数时,即两堆长度相等,将新元素插入到smallHeap ,插入后smallHeapbigHeap长度大1;
  • 当两堆总长度为奇数时,即两堆长度不等,将新元素插入到bigHeap,插入后两堆长度相等;

还要保证插入元素后,两堆仍是保证从下往上递增的顺序性。
那么,每次新元素插入时,都需要先插入到另一个堆,进行重新排序后,再将最值拿出来插入正确的堆中。

  • 当两堆总大小为偶数时,即两堆大小相等,先将新元素插入bigHeap,重新排序后将新的最值拿出并插入到smallHeap
  • 当两堆总大小为奇数时,即两堆大小不等,先将新元素插入smallHeap ,重新排序后将新的最值拿出并插入到bigHeap

3、代码

一、使用一个 list 集合即可

class MedianFinder {
    List<Integer> list = null;
    public MedianFinder() {
        list = new ArrayList<>();
    }
    
    public void addNum(int num) {
        list.add(num);
    }
    
    public double findMedian() {
        Collections.sort(list);
        int len = list.size();
        if(len % 2 == 0){
            return (double)(list.get(len / 2 - 1) + list.get(len / 2)) / 2.0;
        }else{
            return (double) list.get(len / 2);
        }

    }
}

二、双堆

class MedianFinder {

    PriorityQueue<Integer> smallHeap, bigHeap;
    public MedianFinder() {
        smallHeap = new PriorityQueue<>(); // 小顶堆,保存较大的一半
        bigHeap = new PriorityQueue<>((x, y) -> (y - x)); // 大顶堆,保存较小的一半
    }
    
    public void addNum(int num) {
    // 长度为偶数时先放入大顶堆,重新排序后在插入到小顶堆
        if(smallHeap.size() == bigHeap.size()){
            bigHeap.add(num);
            smallHeap.add(bigHeap.poll());
        }else{
        // 长度为奇数时先放入小顶堆,重新排序后在插入到大顶堆
            smallHeap.add(num);
            bigHeap.add(smallHeap.poll());
        }
    }
    
    public double findMedian() {
        if(smallHeap.size() != bigHeap.size()){
            return smallHeap.peek();
        }else{
            return (smallHeap.peek() + bigHeap.peek()) / 2.0;
        }

    }
}

剑指 Offer 43. 1~n 整数中 1 出现的次数

1、题目

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
在这里插入图片描述

2、题解

一、暴力解
这题目乍一看,直接暴力遍历就好了,通过遍历每一个数出现 1 的次数,然后累加起来即可,但是立马被暴击,超时了。

二、数学规律

3、代码

一、暴力解

class Solution {
    public int countDigitOne(int n) {
        int res = 0;
        for(int i = 1;i <= n;i++){
            res += getNum1(i);
        }
        return res;

    }

    public int getNum1(int num){
        int sum = 0;
        while(num > 0){
            if(num % 10 == 1){
                sum++;
            }
            num /= 10;
        }
        return sum;
    }
}
举报

相关推荐

0 条评论