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)$

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

  • 相关阅读:
    nginx升级总结,漏洞升级
    【BUG解决】在git上pull时提示You have not concluded your merge. (MERGE_HEAD exists)
    如何自签名把http网站变成https网站(https自签名方法)
    ifly
    Shell排序和二叉树排序
    C/C++复习笔记(2)
    C/C++复习笔记(1)
    C语言字符串操作
    python+flask
    C语言的一点复习
  • 原文地址:https://www.cnblogs.com/milaohu/p/6085064.html
Copyright © 2011-2022 走看看