同一对角线上的元素列表

时间:2018-03-07 06:07:46

标签: algorithm element counting diagonal

考虑给定的nxn矩阵。输入是n 然后给出(行,列)矩阵中存在的那些元素作为坐标列表。说k这样的元素 总元素n ^ 2,k元素被填充。 Max(k)= n ^ 2,每个元素都被填充。

Q值。查找同一对角线上的数字和元素列表。

1

一种方法是比较每个元素行,每个其他元素的col差值绝对值。如果出现以下情况,2个元素在同一对角 Row2-Row1 == Col2-Col1或 Row2-Row1 == - (Col2-Col1)

如果给出了k个元素,我们有k(k-1)个比较,一个用于正差,一个用于负差(绝对函数也在内部做同样的,比较正负差,所以每个比较两次)

总检查:k(k-1)

2

我们只是沿着每个对角线迭代。如果我们找到2个或更多元素,我们会推送列表中的所有元素。 每个元素访问两次,一次沿着-1斜坡对角线,另一次沿着+1斜坡对角线。

总检查:2n ^ 2

考虑n = 5且k = 8 这是网格中的25个插槽,其中填充了8个插槽

在这种情况下,#2有50个检查,而#1有56个检查。

同样n = 10,k = 15

我们有#1给出210张支票,#2给出200张支票。

算法#2一般不比#1

除非矩阵人口稀少,但我们不知道这种情况,否则k可能很小或很大。我们必须选择1种方法。

对于这个问题,哪种方法#1或#2似乎是更好的选择?

如果适合你,请随意坚持计算并忘记清单。

或许我错过了一些或更好的方法

PS:如果2,1和3,2和1,2是元素,则计数应为3.不要计算相同的元素两次。也可能有5,1和6,2,因此它基本上是2,1 3,2 1,2 5,1 6,2总共5个元素

2 个答案:

答案 0 :(得分:1)

使用任何方便的方法计算对角线(如果我们计算1长度,则有4n-2对角线。)

每个项目都属于两个对角线。只需将这些对角线ID添加到具有counter = 1的哈希映射中,或者如果存在映射条目,则将增量计数器添加到哈希映射中。

如果k与n或更大相比,则由对角线数索引的简单数组将优于map。

P.S。刚刚注意到and list of elements
地图条目还应包含坐标列表。

最后找到具有项目坐标的最大计数器结束提取列表的地图条目。

时间和空间复杂度为O(k)(对于数组的情况,空间O(n))

例如,n = 4,我们从左上角开始计算/对角线(地图F),从右上角开始计算\ diagonals(地图B)。每个方向都有7种可能的对角线。

示例:我们使用坐标(行,列)添加5个点。对角线F(0)与数字1相交,对角线B(2)与数字0相交(我的标签被打破)

enter image description here

(0, 0) increments F(0) and B(3)
(2, 2) increments F(4) and B(3)
(1, 2) increments F(3) and B(2)
(3, 1) increments F(4) and B(5)
(1, 3) increments F(4) and B(1)

毕竟:我们对对角线F(4)和B(3)

的计数器> = 2

修改:获取唯一商品:

将所有对角线项目推入哈希映射(忽略重复)。复杂性是O(k')其中k'是对角线项目的数量

或另一种变体:排序合并列表,然后提取重复项是微不足道的。复杂性是O(k' * log(k'))

答案 1 :(得分:0)

谢谢@MBo,

在您的示例中,有4个元素形成对角线,而不是3 即。 - (0,0)(1,3)(2,2)(1,3)

让我改写一下我的理解 让我们假设我们可以有负数组索引以便于讨论,我们总是可以在代码中将-n加到0和n到2n-1。

我们定义了2个数组Sum和Diff

总和可以在2到2n .. /对角线,(2n-1值)

之间变化

Diff可以在-n和n(2n-1值)之间,包括0,.... \ diagonal

foreach ele in k
elesum=elerow+elecol
elediff=elerow-elecol
push Sum[elesum] , (elerow,elecol)
push Diff[elediff],  (elerow,elecol)
next ele

每个数组中有k个元素,k次迭代

然后我们这样做:

foreach S in Sum
if count S > 2 push final_list,S
Next S

这有最多2n-1次迭代

foreach D in Diff
if count D > 2 push final_list,D
Next D

这也有最多2n-1次迭代。

我们现在有一个final_list = merge(S,D),其中包含对角线中所有元素的row,col(非唯一) 我们现在必须使用独特的final_list。

仅适用于比较部分:

KMAX = N ^ 2

用于比较的总最大n ^ 2 + 4n-2次迭代。

uniquenes的成本可能不一样,每次我通过对角扫描方法推送一个新元素时,我都可以进行in_array检查。我如何在这里做,因为我需要注意,虽然一个元素可能存在于sum数组中,但它可能在diff数组中不存在(到目前为止),但可能会有未来的匹配。

所以我必须保留每个元素的所有Sums和Diffs。

在我的情况下,如果元素已经填充在final_list数组中,我可以简单地设置val(row,col)= 2。然后当扫描另一个倾斜的对角线时,我只需先检查该元素是否> 0,然后如果它是> 1,如果不是,我将它推到final_list并将其设置为2. 你可以做到在S迭代中相同,但在D迭代中,每个元素也必须与现有列表进行比较。

如果是汇编程序代码,我会将其设置为-1而不是2,并使用0和JL执行cmp,JG和JE就足够了。

因此,如果填充所有元素,当我合并它们以执行array_unique时,Sum和Diff将包含n ^ 2个元素。

在我的对角扫描中,我只需要在推动之前检查元素是否在列表中。 在这种情况下你能解释一下吗?

我对你的方法的理解是否正确?