JZ63 数据流中的中位数——大顶堆、小顶堆

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

题解

此题应该着重于考察大顶堆和小顶堆

之所以提供两个函数,就是想让大家动态的获取
比如插入之后,通过getmedian能立马获得中位数,需要动态的更新

具体思想可看:https://leetcode-cn.com/problems/find-median-from-data-stream/solution/shu-ju-liu-de-zhong-wei-shu-by-leetcode/

算法
两个优先级队列:

  • 用于存储较小一半数字的最大堆 max
  • 用于存储较大一半数字的最小堆 min

最大堆 max 允许存储的元素最多比最小堆 min 多一个。因此,如果我们处理了 k 元素:
如果 k = 2 ∗ n + 1 k=2*n+1 k=2n+1,则允许 max 持有 n+1元素,而 min可以持有 n 个 元素。
如果 k = 2 ∗ n k=2*n k=2n,那么两个堆都是平衡的,并且每个堆都包含 n 个元素。
这给了我们一个很好的特性,即当堆完全平衡时,中间值可以从两个堆的顶部派生。否则,最大堆 max 的顶部保留合法的中间值。

添加一个数 num:
将 num 添加到最大堆 max。因为max 收到了一个新元素,所以我们必须为 min 做一个平衡步骤。因此,从 max中移除最大的元素并将其提供给 min 。
在上一个操作之后,最小堆 min 可能会比最大堆 max 保留更多的元素。我们通过从 min 中去掉最小的元素并将其提供给 max 来解决这个问题。

上面的步骤确保两个堆能够平衡
但好像javascript中不提供堆的数据结构,因此如果我们要用大顶堆和小顶堆的思想解,还需要构造堆的构造函数,及维护堆的各种方法,可以在上面提供的链接中找到相应的具体代码。

这里我们先提供一种暴力解法的代码

代码:

let arr = [];
function Insert(num)
{
    // write code here
    arr.push(num);
    let len = arr.length - 1;
    while(len>0){
        if(arr[len] < arr[len-1]){
            [arr[len],arr[len-1]] = [arr[len-1],arr[len]];
            len--;
        }
        else
            break;
    }
}
function GetMedian(){
    // write code here
    if(!arr.length)
        return null;
    else if (arr.length % 2)
        return arr[(arr.length-1)/2];
    else{
        let midIndex = arr.length / 2;
        return (arr[midIndex] + arr[midIndex-1]) / 2
    }
}
在字符串"jz54",我们需要找出字符流第一个不重复的字符。首先,我们可以创建一个HashMap来存储字符和对应的出现次数。 假设字符流每次传入一个字符c: 1. 首先判断HashMap是否已经存在字符c。若存在,则将对应的出现次数加1; 2. 若不存在,则将字符c添加到HashMap,并将出现次数设为1。 3. 然后从字符流取出HashMap第一个出现次数为1的字符,即为第一个不重复的字符。 以下是相应的Java代码: ```java import java.util.HashMap; public class FirstNonRepeatChar { private HashMap<Character, Integer> charMap; public FirstNonRepeatChar() { charMap = new HashMap<Character, Integer>(); } public void processChar(char c) { if (charMap.containsKey(c)) { charMap.put(c, charMap.get(c) + 1); } else { charMap.put(c, 1); } } public char getFirstNonRepeatChar() { for (char c : charMap.keySet()) { if (charMap.get(c) == 1) { return c; } } return Character.MIN_VALUE; // 如果没有不重复的字符,返回一个特殊值 } public static void main(String[] args) { FirstNonRepeatChar f = new FirstNonRepeatChar(); String input = "jz54"; for (int i = 0; i < input.length(); i++) { f.processChar(input.charAt(i)); } char firstNonRepeatChar = f.getFirstNonRepeatChar(); if (firstNonRepeatChar == Character.MIN_VALUE) { System.out.println("字符流没有不重复的字符"); } else { System.out.println("字符流第一个不重复的字符是:" + firstNonRepeatChar); } } } ``` 运行以上代码,输出结果为:"字符流第一个不重复的字符是:j"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值