这是interview question:如何处理整数矩阵以找到O(1)中任何子矩形元素的平均值?正如评论所说,我们应该计算前缀总和。
嗯,这很令人尴尬,但即使问了类似的question,我也没有得到它。
答案 0 :(得分:4)
虽然你有几个合理的答案,但这似乎是一张图片价值数千字的问题。
好的 - 我们想要的是矩形4的区域。然而,我们预先计算的区域仅告诉使用从左上角的原点开始的整个矩形的区域,并且延伸到4的右下角。要计算仅区域4,我们必须减去上方和左侧的区域(1,2和3)。 2&区域3是相同的方式:我们只能从左上角开始,并向右下方延伸。这意味着我们可以得到它们的面积之和,但是矩形1的区域包含在的两个中。
因此,为了得到矩形4的区域,我们在右下角找到了该区域。我们在2和3的右下角找到区域并将它们加在一起。然后我们减去矩形1右下角的区域,因为它包含在我们的总数中两次。这给了我们矩形1,2和3的总面积。我们从矩形4右下角的区域中减去它,这样就可以得到矩形4的区域。
例如,让我们假设我设法让所有这些矩形的大小相同,因此我们将为每个'1'调用该区域。因此,每个矩形右下角给出的区域为:
为了简单起见,让我们将每个定义为pc_area(x)
(即我们在矩形x的右下角得到的预计算区域)。
所以,我们采取:pc_area(4) - (pc_area(2) + pc_area(3) - pc_area(1))
替换数字,我们得到:4 - (2 + 2 -1)
或4-3
,显然给出1,我们最初定义为正确的答案。
答案 1 :(得分:3)
请参阅@Sven Marnach'answer到@Michael链接的帖子。他概述的前缀和算法基于以下思想:如果你已经预先计算了以下元素序列的总和:[0,0],[0,1],[0,2],...,[0, n-1],您可以将常数时间序列[a,b]的总和计算为[0,b] - [0,a-1]。相同的想法可以应用于二维阵列。将(a,b)左上角和(c,d)右下角的子阵列表示为[(a,b),(c,d)]。我们将类似于我们如何在1-D情况下处理序列来处理这样的子阵列。预计算左上角为(0,0)的所有子阵列的总和:[(0,0),(0,0)],[(0,0),(0,1)],[(0, 0),(0,2)],...,[(0,0),(0,m-1)],[[(0,0),(1,0)],[(0,0) ),(1,1)],...,[(0,0),(1,m-1)],...,[(0,0),(n-1,m-1)] 。存在n * m个这样的子阵列,并且可以基于较小子阵列的总和在恒定时间内计算每个子阵列的总和。如果我们现在被要求产生子阵列的总和[(a,b),(c,d)],我们可以找到[(0,0),(c,d)] - [(0,0) ),(a-1,d)] - [(0,0),(c,b-1)] + [(0,0),(a-1,b-1)]。在纸上绘制,你会看到子阵列是如何重叠的,以及为什么我们需要添加最后一个子阵列。
答案 2 :(得分:1)
我认为你被一个矩阵/ nubmers列表的假设误导了。
在这种情况下,要求是不可能的。你能做的最快的是一个基于排序算法的启发式算法,你可以实现O(Log(n))。
但是,只有在存在容错且未分散值的分布时才会有用。
但是,如果您可以控制数据结构,那么您可以很好地解决问题。这样做的常见技术称为prefix sums。
在维基百科上阅读,他们会比我更好地解释它。
但是,让我提供一个非常基本的微不足道的类比,可以解决混乱。
您无法在O(1)中搜索列表中的元素。 Log(n)是您可以做的最好的,如果它已经排序或您之前进行排序。
但是,如果您可以控制数据结构,则可以构建一个哈希索引,您可以直接选择它并使用O(1)。
前缀总和是类似的。它是一个解决问题的数据结构,而不是算法(当然不是算法,而是在线路的另一侧)。