【问题标题】:Subarrays allocation [closed]子数组分配[关闭]
【发布时间】:2014-05-03 15:21:22
【问题描述】:

我有一个数组,它用数字填充,因此它包含空元素和非空元素,实际上由几个数组组成。它可能看起来像这样:

0 х х х 0 х х х 0 0 0 0 0 0
0 x х х х x х х 0 0 0 х х х
0 0 х х х х 0 х 0 0 0 х х х
0 х х 0 х х х х 0 0 х 0 х х
0 х х х 0 0 0 х 0 0 х х х 0
0 0 0 0 0 0 0 0 0 0 0 х х х
0 0 0 0 0 0 0 0 0 0 х х х х
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 xxxxx 0 0 0
0 0 0 0 0 xxxx 0 x 0 0 0

“0”表示空元素
“x”表示非空元素

一个人在这里很容易找到 3 个子数组,但我想知道如何使用程序找到它们。困难在于子数组不完整,即有空元素。 有没有将初始数组切割成子数组的算法,或者任何人都可以帮助我?

附言子数组的坐标 (x1,y1,x2,y2):{2,1,8,5} {11,2,14,7} {6,9,11,10}。也用粗体突出显示

【问题讨论】:

  • 这个人也可以形成超过 3 个子阵列。我的意思是你如何将数组划分为子数组?子数组的数量和空元素的数量是否有相关的成本函数?
  • 它们之间应该至少有一个空行(列)。未定义且应计算的子数组数量。输入只是一个主数组 m*n。可以计算主数组中的空元素和非空元素。换句话说,输入是一个巨大的数组,具有我上面显示的结构,输出是一个数组(n,x1,x2,y1,y2),其中 n 是索引,x1,x2,y1,y2 是坐标一个子数组。
  • 对不起,输出应该是一个Array(n,1 to 4),其中n是子数组的索引,1到4是它的坐标x1,y1,x2,y2
  • 问题还没有明确定义。 “它们之间至少有一个空行”是什么意思?一个完整的空行或列?而且,为什么不直接取整个矩阵呢?它还包含所有非零元素。优化目标是什么?最小面积?最大矩形数?

标签: arrays algorithm logic


【解决方案1】:

您可以使用联合查找数据结构在 O(NM) 时间内解决此问题。请按以下步骤操作:

Step1:在矩阵中为相邻的填充元素生成连续的水平线。并用不同的数字标记这些行。

对于这个改变的矩阵

0 х х х 0 х х х 0 0 0 0 0 0
0 x х х х x х х 0 0 0 х х х
0 0 х х х х 0 0 0 0 0 х х х
0 0 0 0 0 0 0 0 0 0 х х х х
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 x x x x x 0 0 0
0 0 0 0 0 x x x x 0 0 0 0 0

矩阵的不同行会变成:

0 1 1 1 0 2 2 2 0 0 0 0 0 0
0 3 3 3 3 3 3 3 0 0 0 4 4 4
0 0 5 5 5 5 0 0 0 0 0 6 6 6
0 0 0 0 0 0 0 0 0 0 7 7 7 7
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 8 8 8 8 8 0 0 0
0 0 0 0 0 9 9 9 9 0 0 0 0 0

Step2:现在初始化一个 Union Find 数据结构,其中所有不同的行在数据结构中作为单独的集群/集合。

Step3:开始迭代矩阵的所有列。每当您遇到新行的开头时,请检查该行的正上方或正下方是否有某行。如果在上面或下面存在这样的行,则将与数据结构中相邻行对应的两个集合合并。

Step4:现在你已经在算法的末尾有了所有不同的线簇,你可以很容易地计算出簇的边界。因此,您拥有所有不同的子数组。

运行时间:O(NM) 考虑到我们使用带有路径压缩的加权快速联合查找数据结构,提供 O(α(n)) 时间(其中 α 是 inverse Ackermann function)工会行动。而且由于逆阿克曼函数增长非常缓慢,我将其视为常数。

编辑:在这种情况下,所描述的算法将失败(如 cmets 中的用户烧杯所述)

1 1 1 1 1
2 0 0 0 3
0 0 4 0 0

为了处理这些类型的情况,除了提到的数据结构之外,我们将维护一个数组,该数组将包含每行占用的矩形。因此,当我们将第 2 行与第 1 行合并时,第 2 行的值将变为 0...4,这表明存在一个覆盖第二行索引 0 到 4 的矩形。现在,当在第 3 步中考虑第 4 行时,它将检查上方或下方的点是否被某个矩形覆盖。因此它将第 4 行的集群与第 2 行的集群合并。

算法的其他部分将保持不变,除了我们现在检查相邻点是否被某个矩形覆盖。

我们为所有行维护的额外信息将增加运行时间。每当我们在步骤 3 中考虑矩阵列时,我们可能需要做 O(n) 额外的工作。所以运行时间上升到O(N^2 * M)

【讨论】:

  • 这基本上是Connected Component Labeling 算法,只要您可以确定所有非零元素都连接到其子数组的其余部分,它就可以正常工作。如果没有,您可能会错过子数组的行/列。
  • 我不明白你的意思。我认为它适用于所有测试用例。您是否有一些解决方案可能失败的测试用例?
  • 当然:row1 = 1 1 1 1 1;第2行=1 0 0 0 1;第 3 行 = 0 0 1 0 0。可能 row3 只是它自己的子数组,但如果您水平复制行以使 row3 为0 0 1 0 0 0 0 1 0 0 ...,则可能更难消除。
  • 一个非常好的案例。我将编辑我的答案来处理这种情况。
  • 因文,非常感谢!!!我有一个类似的想法,但你显着改进并完美地形式化了它。也非常感谢烧杯。我认为对于我的问题,提供额外的检查是过度的,尽管知道可能的错误非常有用。由于我的评分较低,我无法为您投票,但我非常感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
  • 2015-01-10
  • 1970-01-01
相关资源
最近更新 更多