维护实时中位数和秩

1.实时中位数 leecode 295

/*
 * solution :
 * 1.利用PriorityQueue新建两个堆,一个大根堆maxHeap(需要自己实现比较器),一个小根堆minHeap
 * 2.插入元素时,让大根堆的堆顶元素始终小于等于中位数,小根堆的堆顶元素始终大于中位数
 * 3.所以元素个数为奇数个时,大根堆比小根堆多一个元素,且中位数为大根堆堆顶元素;元素个数为偶数时,两堆一样高,中位数为两堆顶元素的平均值
 * 4.主要是插入元素时,要根据两堆的size来与堆顶元素进行比较,决定插入哪个堆
 */
public class S295 {
    private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new MaxComparator());
    private PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
    // Adds a number into the data structure.
    public void addNum(int num) {
        if (maxHeap.size() > minHeap.size()) {
            if (num < maxHeap.peek()) {
                minHeap.offer(maxHeap.poll());
                maxHeap.offer(num);
            } else {
                minHeap.offer(num);
            }
        } else {
            if (maxHeap.size() == 0) {
                maxHeap.offer(num);
            } else {
                if (num > minHeap.peek()) {
                    maxHeap.offer(minHeap.poll());
                    minHeap.offer(num);
                } else {
                    maxHeap.offer(num);
                }
            }
        }
    }

    // Returns the median of current data stream
    public double findMedian() {
        if (maxHeap.size() == 0)
            return -1;
        if (maxHeap.size() == minHeap.size()) {
            return (double)(maxHeap.peek() + minHeap.peek()) / 2;
        } else {
            return maxHeap.peek();
        }
    }
}
class MaxComparator implements Comparator<Integer> {
    @Override
    public int compare(Integer a, Integer b) {
        if (a > b) {
            return -1;
        } else if (a < b) {
            return 1;
        } else {
            return 0;
        }
    }
}

2.实时秩  某个数的秩是当前数组中小于等于这个数的数的个数  程序员面试金典 P267 11-8

/*
* solution:
* 维护实时秩其实就是使数组始终有序,很容易想到了二叉查找树,不过要给每个节点实时记录左子节点个数leftSize。
* 我们从二叉查找树的根节点开始查找,会出现三种情况
* 1. 当前节点值等于当前值,则当前值的秩则是当前节点的leftSize
* 2. 当前节点值大于当前值,则要往当前节点的左子节点继续查找
* 3. 当前节点值小于当前值,则当前值的秩首先得加上当前节点值的leftSize + 1(1代表当前节点本身),再往右继续查找
*/

import java.util.*;

public class Rank {
    RankNode root = null;
    public int[] getRankOfNumber(int[] A, int n) {
        // write code here
        int[] rank = new int[n];
        for (int i = 0; i < n; i++) {
            track(A[i]);
            rank[i] = root.getRank(A[i]);
        }
        return rank;
    }
    public void track(int val) {
        if (root == null)
            root = new RankNode(val);
        else
            root.insert(val);
    }
}
class RankNode {
    RankNode left = null, right = null;
    int val = 0;
    int leftSize = 0;
    public RankNode(int val) {
        this.val = val;
    }
    public void insert(int val) {
        if (val <= this.val) {
            if (this.left != null)
                this.left.insert(val);
            else
                this.left = new RankNode(val);
            this.leftSize++;
        } else {
            if (this.right != null)
                this.right.insert(val);
            else
                this.right = new RankNode(val);
        }
    }
    public int getRank(int val) {
        if (val == this.val)
            return this.leftSize;
        if (val > this.val) {
            if(this.right == null)
                return -1;
            return this.leftSize + 1 + this.right.getRank(val);
        }
        if (this.left == null)
            return -1;
        return this.left.getRank(val);
    }
}

时间: 2024-10-27 03:51:32

维护实时中位数和秩的相关文章

bzoj 1367: [Baltic2004]sequence(中位数+可并堆)

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MB Submit: 935  Solved: 351 [Submit][Status][Discuss] Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18. R=13 Source [Submit]

54. 数据流中的中位数

思路:AcWing 54. 数据流中的中位数 将数组分成两半,一个大顶堆和一个小顶堆,大顶堆维护小于中位数的所有元素,小顶堆维护大于中位数的所有元素,两个堆的元素数量差不能超过2,超过2就互相匀一匀. 代码: class Solution { priority_queue<int> maxHeap;//大顶堆维护小于中位数的所有元素 priority_queue<int, vector<int>, greater<int>> minHeap;//小顶堆维护大

BZOJ 1112 [POI2008]砖块Klo(可持久化线段树)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1112 [题目大意] 给出一个数列,对于一个操作,你可以对一个数+1,或者一个数-1, 问若使得数列中出现长度为m的连续相同的数,最少需要的操作数. [题解] 我们发现对于固定区间求最小操作,等价于求区间中数距离中位数差值和最小, 我们发现区间中位数可以利用主席树求区间kth来实现, 同时在主席树上维护权值线段树的区间真值和,那么对于每个区间中的数, 就能分别维护比中位数小的部分的和以

【bzoj4071】[Apio2015]巴邻旁之桥 Treap

题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000.相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度.区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对. 城市中有 N 个居民.第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上.一个居民的房子和办公室可能分布在河

cgroup原理简析:进程调度

本篇来探究下cgroup对cpu的限制机制,前文提到过cgroup也是通过进程调度子系统来达到限制cpu的目的,因此需要了解下进程调度子系统. 因为是介绍cgroup的文章,因此只介绍进程调度中与cgroup密切关联的部分,详细完成的进程调度实现可参考进程调度的相关资料. 本文分为三个部分,首先介绍进程调度中的调度算法,在该基础上引入组调度,最后结合前面文章(cgroup原理简析:vfs文件系统)来说明上层通过echo pid >> tasks, echo n > cpu.shares等

1109解题报告

[概述] 现场A掉T1和T2,T3骗了10分,总共210,若这是2016的NOIP试题,恐怕要跪. 这次的题难度似乎是倒过来的,T3应该是最简单的,而T2是最难的. 但是我一直在啃T2,以至于最后放弃了T3. 这启示着我们,先把所有题读完是多么的重要. T1.prime [题目大意] 给你一个区间,求区间内素数的个数. [吐槽] 正解:先筛出50000以内的素数,然后在用这些素数将区间内的合数筛掉. 我的江湖解法:看到这题,我不禁想说这不是Rabin_Miller的模板吗,于是果断敲了一遍,顺利

bzoj-1112 砖块Klo

题意: 给出一个长度为n的数列,现要将其连续k个数变成一样的: 每次可以对一个数+1或-1,问最小操作次数: 1<=k<=n<=100000,0<=数列中的数<=1000000: 题解: 感觉是一道好题吧: 首先有这样一个结论:将这些数置为中位数所需要的操作数最小: 证明啥的网上关于中位数的一大堆?反正我不会: 然后我们要做的就是: 1.动态维护区间中位数: 2.对一个区间更新答案: 有的同学选择了平衡树解决.. 实际上这个题用权值树状数组就好了,虽说多个log= =: 中位

高性能Mysql——Schema与数据类型优化

良好的逻辑设计和物理设计师高性能的基石 一.选择优化的数据类型 更小的通常更好 占用更小的磁盘.内存.CPU缓存和处理时需要的CPU周期 简单就好 操作需要更少的CPU周期,例如:整型比字符型操作代价更低,以为字符集和校对规则使字符比整型更复杂.应该使用Mysql内建的类型而不是字符串来存储日期和时间,另外一个是应该用整型存储IP地址. 尽量避免NULL 通常情况最好指定列为not null,除非真的需要存储null值.如果查询包含null的列,对Mysql的来说更难优化,null的列是的索引.

51nod1785数据流中的算法

51nod近日上线了用户满意度检测工具,使用高级人工智能算法,通过用户访问时间.鼠标轨迹等特征计算用户对于网站的满意程度. 现有的统计工具只能统计某一个窗口中,用户的满意程度的均值.夹克老爷想让你为统计工具添加一个新feature,即在统计均值的同时,计算窗口中满意程度的标准差和中位数. Input 第一行是整数n与k,代表有n次操作,时间窗口大小为k.  (1 <= n <= 10^6, 1 <= k <= 100) 接下来的n行,每行代表一次操作.操作有“用户访问”.“查询均值