1.写在前面
去年因为某项目遇到模型卡顿问题,分析原因发现是模型中点没有进行合并,故而设计了点合并的技术方案,由于某些原因该方案未能实施,仅仅是方案,放在技术方案堆里,以一篇文档形式。
平时的积累尤其重要,尝试更优,加之日积月累,会有比较大的进展和进步,技术如此,工作也一样。
平时面试偶尔也会以该题目为背景问一下面试者,看看思路怎样,有想法还不错的,也有不知所措的...好了,闲扯到这里,开始吧。
2.思路
2.1.方案一
ifcOpenShell是将点的hash作为key,建立map,map<pair<pair<x,y>, z>, T>,这样利用map(特化的红黑树)的查取效率,效率较高,查取一次复杂度为o(logN),整个点合并过程复杂度为o(N*logN)。这是一种实现成本低,且效率较高的方式,值得使用或借鉴。
2.2.方案二
曾经有面试者这样回答:
以每个点为中心,以空间对齐的方式建立一定范围的格子,比如坐标为(102.3, 5.6, 9.8)的点建立格子的范围为x:[102,103),y:[5,6),z:[9,10),格子对齐空间的位序为x:103,y:6,z:10,这样,n个点建立格子,然后建立完也就点合并完成,复杂度为o(N),此时如果某个格子有多个点,就认为这些点是误差范围内相同的点,就可以合并。
该思路对吗?
如果只建立格子而不进行格子间的去重合并,那么这个过程复杂度确实是o(N),但是这是满足不了要求的,因此需要对格子进行去重归并,单单是归并,如果是高效的方法,复杂度也是o(N*logN)。
面试的同学又说了,
在建立格子的过程中进行格子查询归并,比如格子对齐空间的位序为x:103,y:6,z:10,那么就去一个三维数组中利用下表索引快速定位的方式判断是否存在,复杂度为o(1),这样整体复杂度还是o(N)。
这样的说法正确吗?
我们来推敲一下,数组存储空间是连续的,下表索引定位复杂度确实是o(1),如果存在这样符合条件的数组就可以,那么存在吗?前提是对点列表所属三维空间进行全区域覆盖的格子建立,形成全区域的覆盖的三维数组,然后每建立一个格子,就去进行代价为3*o(1)的查询,返回格子索引(即合并后点的索引)。看出问题了没?“对点列表所属三维空间进行全区域覆盖的格子建立,形成全区域的覆盖的三维数组”这个过程复杂度为多少?o(1)~o(n^3)?最坏为多少?这种方式恐怕是捡了芝麻,丢了大西瓜。
那么可以在上述思路的基础上进行改进吗?
可以的,无须建立全空间区域覆盖的格子,将格子的三个索引作为key进行搜索,其实和上述方案一是一样的了。
2.3.方案三
利用布尔短路运算、红黑树、嵌套的动态生长的红黑树思路进行方案设计,
看到这里应该还是困惑,这有什么高效吗?
布尔短路运算的特点是发现不一致即返回,无须进行后续计算,
红黑树的特点是搜索高效,复杂度为o(n),
哦?好像懂了,懂了?那么嵌套的红黑树又是作甚呢?
主要是用来优化内存使用,嗯?
如果10个点的x坐标一样,那么即存储一份x数据,如果是map<pair<pair<x,y>, z>, T>的方式,那么岂不是要存10份x,y,z数据?大概率是的。
那为什么要红黑树嵌套后为什么还要动态生长呢?主要是为了和布尔短路运算一起使用,搜索的过程中,当判断第一层哈希值(x)一样时才进行下一层哈希值的计算(此时就是树的生长过程),如果不一样,那么对于该目标点,仅计算第一层哈希值即可,返回点索引值。
想一想,计算目标点哈希值复杂度为多少?o(1)~3*o(1),相对于上面的方案的3*o(1)是不是高效了些?当然查询的过程也一样,短路运算。
实际上该方案复杂度仍为o(N*logN),但是系数相比降下来了,而且内存占用也少,对于极端的情况,
- n个点都一样:复杂度为o(N),占用内存为常量级(3坐标分量对应的float+3个单元素的红黑树),此时效率和内存和方案一相差无几,几乎一样。
- n个点都不一样(x都不一样):复杂度为o(N*logN),但是!只计算了n个点的x哈希值(比如x*100,保留两位小数对比),只存储了n个点的x哈希值;如果是方案一呢?计算n个点的x,y,z哈希值,且存储x,y,z哈希值,查询过程倒是都是短路的,判断x不一样即退出。
明白了没?方案三整体复杂度没有下降,但是其效率系数和内存系数均有提升,因为实际点列表情况基本都介于上述两个极端之间。
进行完点合并之后,“嵌套的动态生长的红黑树”是一颗不完全生长的树,即存在x,y都一样的点对应的分支是完全生长的,其他的都是不完全生长的,内存和计算过程均有精简。
2.4.方案四
将x,y,z计算一个哈希值,这样建立一个map就可以,省事。这样理论可行,但是将三个坐标分量压缩为一个哈希值会有哈希计算重复的概率,也就是有不准确的概率,可能会把两个根本不一样的点认为是同一个点。
3.总结
平时的积累尤其重要,尝试更优,加之日积月累,会有比较大的进展和进步,技术如此,工作也一样。
该思路可以扩展开来,用于更多的场景优化。
不要吝啬你的点赞、收藏、评论,这也是一种表达。
熬夜伤身体,也伤脑...