我认为应该这么做:
考虑这么一个类似的问题:
m x n 的0 , 1矩阵,要求:
对于每个 "1", 把以这个 “1” 为左上角,以其位置 + (k,k) 为右下角的正方形内所
有点涂色。 要求复杂度 O(m x n)
再说具体一点,我们考虑一个新的问题,这时候对于每个 “1” , 假设位置在 (i,j),
不是要求涂曼哈顿距离了,而是要求 涂 满 (i,j) 为左上角 和 (i+k, j+k) 为右下
角的正方形。
这个问题有什么好处呢?且看如下图形(对应 k = 3 的情形):
3 2 1
2 2 1
1 1 1
如果我们把原先矩阵里面的每个 “1” 都换成 k,然后用 “从左上角开始,以矩形圈
的方式往外扩散(具体参见上图中 "1" 的位置 对应的圈)” 的loop顺序对当前点右
方和下方最
邻近的三个点进行值的update就行了。在当前的 (i,j)位置时,需要update (i+1,j) (
i,j+1) 和 (i+1,j+1) 的值, update方法就是,如果新的点的值小于 "(i,j)位置的值
-1" 时,那么就把他update成 "(i,j)位置的值 - 1"。 这样处理完之后,所有正整数
的地方都是要着色的地方,复杂度是 O(m x n), 不需要额外的空间。
以上算法的关键是,根据涂色要求的本身需要设计一个合理的遍历方式,使得可以不重
复的回头看已经涂过的地方。因为这个类似的变种题更容易观察出这种遍历方式,所以
作为引子先说一下。
这时候考虑原题,就简单了。我们用类似的算法,标记规则是这样的 (假设 k = 3)
0 0 1 0 0
0 1 2 1 0
1 2 3 2 1
0 1 2 1 0
0 0 1 0 0
然后遍历方式是什么呢?是这样的:
从任意一个标记为 k 的点开始 (先预处理矩阵,把所有 “1” 改成 k),以圈状的
方式向矩阵外围遍历(参见上图 “1” 构成的菱形圈),然后每次update 该点周围上
下左右的四个位置。