在2Darrays中找到峰值的算法

假设我在java int[][] array有一个2D累加器int[][] array 。 该数组可能如下所示:

(x和z轴表示数组中的索引,y轴表示值 – 这些是int[56][56] ,值为0~4500) 数组样本1

要么

数组样本1

我需要做的是在arrays中找到峰值 – 第一个峰值有2个峰值,第二个arrays有8个峰值。 这些峰值总是“明显的”(峰值之间始终存在间隙),但它们不必像这些图像那样相似,它们可能或多或少是随机的 – 这些图像不是基于真实数据,只是样本。 真正的arrays可以有5000×5000的大小,峰值从几千到几十……算法必须是通用的,我不知道arrays或峰值有多大,我也不知道那里有多少个峰值是。 但我确实知道某种阈值 – 峰值不能小于给定值。

问题是,一个峰可以由附近的几个较小的峰组成(第一个图像),高度可以是非常随机的,并且在一个arrays中大小可以显着不同(大小 – 我的意思是它在arrays中占用的单位数 – 一个峰值可以包含6个单位,其他峰值可以包含90个单位。 它也必须快速(全部在1次迭代中完成),arrays可能非常大。

任何帮助表示赞赏 – 我不希望你的代码,只是正确的想法:)谢谢!


编辑:你询问了域名 – 但它很复杂,而且它无法解决问题。 它实际上是一个带有3D点的ArrayLists数组,如ArrayList [] [],并且有问题的值是ArrayList的大小。 每个峰包含属于一个簇的点(在这种情况下为平面) – 该数组是算法的结果,它对点云进行分段。 我需要在峰值中找到最高值,这样我就可以将“最大”的arraylist中的点拟合到一个平面,从中计算一些参数,然后正确地聚集来自峰值的大部分点。

他对使用某种优化启发式估计全局最大值并不感兴趣 – 他只想在多个独立的簇中找到最大值。

这些峰值总是“明显的”(峰值之间始终存在差距)

基于你的图像,我假设你的意思是总是有一些0分隔簇? 如果是这种情况,您可以使用简单的泛洪填充来识别集群。 您还可以在执行洪水填充时跟踪每个群集的最大值,因此您既可以识别群集又可以同时找到它们的最大值。

这也是你能够获得的最快速度 ,而不依赖于启发式(可能会返回错误的答案),因为每个集群的最大值可能是集群中的任何值,因此您必须至少检查一次它们。


请注意,这将遍历数组中的每个项目。 这也是必要的,因为(根据您提供给我们的信息) ,arrays中的任何单个项目都有可能成为其自己的集群(这也会使其成为峰值) 。 arrays中有大约2500万个项目,这在现代计算机上只需要几秒钟。

这可能不是最佳解决方案,但由于问题听起来有点流畅,我会把它写下来。

  1. 构造超过最小阈值的所有值(和坐标)的列表。
  2. 按高度降序排序。
  3. 第一个元素将是最大峰值,将其添加到峰值列表中。
  4. 然后下拉列表,如果当前元素超过所有现有峰值的最小距离,则将其添加到峰值列表中。

这是一个线性描述,但所有步骤(除了3)都可以简单地并行化。 在步骤4中,您还可以使用覆盖图:一个二维布尔数组,显示哪些坐标已被附近的峰“覆盖”。

(注意事项:一旦你改进了标准,这个解决方案可能会变得完全不可行,但总的来说它是有效的。)

模拟退火或爬山是人们立即想到的。 这些算法虽然不能保证找到所有峰值。

但是,如果您的“峰值”以0的值作为间隙分隔,则连接组件分析可能会有所帮助。 如果区域连接的值大于0(或者如果您有一个特定的阈值,标签区域已连接超过该阈值),您可以将区域标记为“已连接”,然后您的组件数量将是您的峰值数量。 然后,您还可以执行另一次数组传递以查找每个组件的最大值。

我应该注意,连通分量可以在线性时间内完成,找到峰值也可以在线性时间内完成。