考虑给定的nxn矩阵。输入是n 然后给出(行,列)矩阵中存在的那些元素作为坐标列表。说k这样的元素 总元素n ^ 2,k元素被填充。 Max(k)= n ^ 2,每个元素都被填充。
Q值。查找同一对角线上的数字和元素列表。
一种方法是比较每个元素行,每个其他元素的col差值绝对值。如果出现以下情况,2个元素在同一对角 Row2-Row1 == Col2-Col1或 Row2-Row1 == - (Col2-Col1)
如果给出了k个元素,我们有k(k-1)个比较,一个用于正差,一个用于负差(绝对函数也在内部做同样的,比较正负差,所以每个比较两次)
总检查:k(k-1)
我们只是沿着每个对角线迭代。如果我们找到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个元素
答案 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相交(我的标签被打破)
(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个元素。
在我的对角扫描中,我只需要在推动之前检查元素是否在列表中。 在这种情况下你能解释一下吗?
我对你的方法的理解是否正确?