用相邻单元格的平均值替换矩阵中的每个单元格

时间:2017-07-04 18:38:01

标签: algorithm matrix

要求:必须就地完成。

例如:

给定矩阵

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

应该用3 * 3个相邻单元的总和及其自身的平均值来代替:

(1+2+4+5)/4,       (2+1+3+4+5+6)/6 ,            (3+2+6+5)/4
(1+2+5+4+7+8)/6,   (1+2+3+4+5+6+7+8+9)/9,       (2+3+5+6+8+9)/6
(4+5+7+8)/4,       (4+5+6+7+8+9)/6,             (5+6+8+9)/4

是:

All floating number convert to int

3,      3.5(3), 4             3, 3, 4
4.5(4),  5, 5.5(5)  =>        4, 5, 5
6,      6.5(6), 7             6, 6, 7

我试图迭代矩阵并更新每个单元格,但我发现这会影响未来的计算:

说我更新了原来的1到3,但是当我尝试更新原版2时,原版1现在变为3。

复制原始矩阵以计算平均值是一种解决方法,但这是一个坏主意,我们可以在不使用那么多空间的情况下实现这一目标吗?

2 个答案:

答案 0 :(得分:2)

在大多数情况下,您应该只创建原始矩阵的副本,并使用它来计算平均值。除非创建矩阵的副本将使用比可用内存更多的内存,否则开销应该可以忽略不计。

如果你有一个真正的大矩阵,你可以使用“滚动”备份(缺少一个更好的术语)。假设您逐行更新单元格,并且您当前在行 n 中。您不需要备份行 n-2 ,因为这些单元格不再相关,并且行 n + 1 都没有,因为它们仍然是原始的值。所以你可以保留前一行和当前行的备份。每当您前进到下一行时,丢弃上一行的备份,将当前行的备份移动到上一行,并创建新当前行的备份。

一些伪代码(不考虑任何边缘情况):

previous = []  # or whatever works for the first row
for i in len(matrix):
    current = copy(matrix[i])
    for k in len(matrix[i]):
         matrix[i][k] = previous[k-1] + ... + current[k] + ... matrix[i+1][k+1] / 9
    previous = current

(您也可以保留 next 行的备份,这样您就可以只使用所有值的备份行,而不必进行区分。)

答案 1 :(得分:0)

您必须为结果数据提供某种缓存,以便您可以继续引用原始数据。我认为没有办法绕过它。

如果数据集很大,您可以通过使用较小的数据缓冲区(如查看锁孔)进行优化,并在更新时“滚动”输入矩阵。在您的情况下,您可以使用小至3x3的缓冲区。 这是速度和空间之间的妥协。缓冲区越小,性能越差。

要显示问题,请从数据集的左上角(0,0)开始:
(为简单起见,结果值向下舍入)

第一步:更新前4个单元格(填充缓冲区)

// Data Set        // Data Viewport // Result Set
01,02,03,04,05     01,02,03         04,04,??
06,07,08,09,10     06,07,08         06,07,??
11,12,13,14,15     11,12,13         ??,??,??
16,17,18,19,20
21,22,23,24,25

然后每次迭代..
(用[xx]表示的新值)

++从结果集

更新数据集中的第一列
// Data Set        // Data Viewport   // Result Set
[04],02,03,04,05   01,02,03         04,04,??
[06],07,08,09,10   06,07,08         06,07,??
 11 ,12,13,14,15   11,12,13         ??,??,??
 16 ,17,18,19,20
 21 ,22,23,24,25

++ shift数据视口和结果集右1列

// Data Set        // Data Viewport // Result Set
[04],02,03,04,05   02,03,04         04,[03],??
[06],07,08,09,10   07,08,09         07,[08],??
 11 ,12,13,14,15   12,13,14         ??, ?? ,??
 16 ,17,18,19,20
 21 ,22,23,24,25

++更新结果集的中间列

// Data Set        // Data Viewport // Result Set
[04],02,03,04,05   02,03,04         04,[05],??
[06],07,08,09,10   07,08,09         07,[08],??
 11 ,12,13,14,15   12,13,14         ??, ?? ,??
 16 ,17,18,19,20
 21 ,22,23,24,25

在接下来的迭代中,数据状态为:

// Data Set        // Data Viewport // Result Set
04,[04],03,04,05   03,04,05         05,[06],??
06,[07],08,09,10   08,09,10         08,[09],??
11, 12 ,13,14,15   13,14,15         ??, ?? ,??
16, 17 ,18,19,20
21, 22 ,23,24,25

..等等

不要忘记处理其他边缘情况。

* 数据视口表示仅用于可视化。在代码中,实际视口将是结果缓冲区。