雷达采样直方图从 O(N×M) 优化到 O(N) 单遍桶计数
背景
雷达图渲染前要统计采样值的分布——算百分位、做增益和对比度映射,这步一般叫”采样直方图”。打开一个多文件的测线时,每打开一个文件都得算一遍。
原来的 O(N×M)
最早的做法是”对每个待统计的输出桶,把所有采样点扫一遍,数有多少落进这个桶”。N 个采样点 × M 个桶,复杂度 O(N×M)。单文件几百万采样点的时候,光这一步就把打开速度拖慢一大截,多文件叠在一起更明显。
改成 O(N) 单遍桶计数
其实直方图没必要每个桶都扫一遍数据。一趟遍历,把每个采样点直接扔进它对应的桶就行了:
fun histogram(samples: IntArray, min: Int, max: Int, bucketCount: Int): IntArray { |
几个细节:range 用 coerceAtLeast(1) 兜底,防止 max == min 时除以零;算 idx 时先转 Long 再乘 bucketCount,避免采样值很大时相乘溢出;最后 coerceIn 把正好等于 max 的点按回最后一个桶,防止数组越界。一趟下来 O(N) 完事,桶数 M 不再参与复杂度。
效果
多文件雷达图加载快了很多,这一步从肉眼可见的卡顿变成基本没感觉。而且这是个公共算法,数据处理、层位识别、病害标注这些模块都调它,改一处,全都跟着快了。
直方图、分桶统计这类活,单遍桶计数就够了。以后看到”对每个桶扫一遍数据”的写法,基本都能照着改成单遍 O(N)。我的体会是,先把算法复杂度降下来再去想并发,往往比一上来就堆线程省事。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CYK's Blog!
评论
