zoukankan      html  css  js  c++  java
  • 算法随笔(一):动态维护分位数(第N大数,The N-th element)

    查找分位数的典型算法是分治法$T(n)=O(n)$。但是对于动态数组来说,依然有优化空间。

    问题描述:交易员在策略中要维护一个定长价格序列(N=3000),交易所每推过来一个新的价格,需要从头部插入它,同时从尾部移走最早的价格。之后,获取它的10%分位数和90%分位数。根据分位数来获得交易信号。

    最原始的做法是:每次更新价格后,排序,然后取10%,90%分位数。在实盘运行时自然没有问题,但是回测速度特别慢。因为它的时间复杂度是$T(n)=O(nlog n)$

    使用分治法代替排序过程后,时间复杂度为$T(n)=O(n)$。依然不够快:

    最终做法:

     1、建立一个Queue(内部实现:循环数组),来按时间顺序存放价格。

    2、建立三个SortedSet(内部实现:排序二叉树): LeftSet,MiddleSet和RightSet。分别保存序列中最小的10%,中间的80%和最大的10%和价格。

    每来一个价格p:

    1、从Queue头部插入p,从尾部弹出最老的数据q。时间复杂度:$T(n)=O(1)$

    2、从LeftSet, MiddleSet,RightSet三个集合中找到q,删除。若q在LeftSet中,删除后LeftSet的元素将少于10%。这时将MiddleSet中最小值移动到LeftSet中,再将RightSet的最小值移入MiddleSet。其他情况以此类推。时间复杂度:$T(n)=O(log n)$

    3、p插入LeftSet,这时候LeftSet中元素个数超过10%。所以将LeftSet最大值移入MiddleSet,在把MiddleSet最大值移入RightSet。最后删除RightSet中的最大值。时间复杂度:$T(n)=O(log n)$

    4、获取10%分位数=LeftSet.Max,90%分位数=RightSet.Min。时间复杂度:$T(n)=O(log n)$

    这样,整个操作时间复杂度降为$T(n)=O(log n)$

    当然,排序二叉树也可以用堆来代替。实现略有不同,这里省略。

  • 相关阅读:
    又到黄金季节,该跳槽吗?怎么跳?
    分布式事务 6 个技术方案
    15 个 MyBatis 技巧,赶紧收藏吧!
    你的工资被倒挂了吗
    终于知道 Java agent 怎么重写字节码了
    每天的工作,你腻了吗?
    10 分钟轻松学会 Jackson 反序列化自动适配子类
    SpringMVC异步处理的 5 种方式
    Linux Cron 定时任务
    人类简史、软件架构和中台
  • 原文地址:https://www.cnblogs.com/milaohu/p/6085064.html
Copyright © 2011-2022 走看看