破解编码面试,第 6 版,1.7
Cracking the Coding Interview, 6th edition, 1.7
给定一个由 nxn 矩阵表示的图像,其中图像中的每个像素为 4 个字节,编写一个将图像旋转 90 度的方法。 (到位)
我做了一个低效的解决方案,即将每一行复制到一个临时文件,然后执行交换,花费了 o(N) space,下面的实际解决方案更好,但我不明白。
def rotate_matrix(matrix):
'''rotates a matrix 90 degrees clockwise'''
n = len(matrix)
for layer in range(n // 2):
first, last = layer, n - layer - 1
for i in range(first, last):
# save top
top = matrix[layer][i]
# left -> top
matrix[layer][i] = matrix[-i - 1][layer]
# bottom -> left
matrix[-i - 1][layer] = matrix[-layer - 1][-i - 1]
# right -> bottom
matrix[-layer - 1][-i - 1] = matrix[i][- layer - 1]
# top -> right
matrix[i][- layer - 1] = top
return matrix
上面的代码是Python的解决方案,
我不明白 for 循环,为什么它在 n//2 范围内,从第一层到 n-layer-1。
另外,为什么题目提到4个字节好像是无用的信息。
谢谢!
考虑 n
是奇数还是偶数很重要,因为必须以细微不同的方式解决问题。不过,在任何一种情况下,正方形都可以分解为象限。
n
为奇数:
正方形被分解成四个矩形象限。在 double for-loop 的每次迭代中,恰好有 4 个元素被旋转,每个象限一个。永远不会访问中间元素,因为它在旋转中保持在中间。
+-------+---+
| x x | x |
+---+---+ |
| x | x | x |
| +---+---+
| x | x x |
+---+-------+
n
偶数大小写:
矩阵被分解成 4 个正方形象限。同样,在 double for-loop 的每次迭代中,恰好旋转了 4 个元素,每个象限一个。
在偶数情况下,每个元素都必须移动(即没有完美的中心元素)。
+-------+-------+
| x x | x x |
| | |
| x x | x x |
+-------+-------+
| x x | x x |
| | |
| x x | x x |
+-------+-------+
n // 2
和 n - layer - 1
只是变相的下限和上限功能。 n
is odd case 需要 floor 和 ceiling。这些值用于在其中一个象限上设置迭代。然后,对于 一个 象限中存在的许多元素,4 次交换发生在适当的位置(在 top
临时值的帮助下)。
基本上我们通过从矩阵的外边界到内核来旋转元素,顺时针交换项目。
我们以下面的矩阵为例:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
在第一次迭代中我们关心的是外部元素:
1 2 3 4
5 x x 8
9 x x 12
13 14 15 16
我们开始(内循环)顺时针交换所有元素。在我们的示例中,我们将 4(将其存储在临时变量中)替换为 1。之后,我们将 1 替换为 13,依此类推。最后,我们用保存的 4 替换 16。我们继续这样做,直到所有元素都被交换。所以在外循环的第一次迭代之后,我们的数组看起来像这样:
13 9 5 1
14 6 7 2
15 10 11 3
16 12 8 4
之后我们进入下一层。在我们的例子中,我们现在看看:
x x x x
x 6 7 x
x 10 11 x
x x x x
我们再次将所有元素一一交换,如上所示。我们有 floor n/2 次迭代,因为对于不均匀的 n,最后一次迭代给我们留下了一个元素,显然不需要旋转。
这给我们留下了:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
对于像 c 这样我们必须手动管理内存的语言,需要 4 个字节。它们的起源很可能是每个像素由 3 种颜色(红色、绿色和蓝色)组成,并且每种颜色由 8 位(0-255)表示。此外,不透明度可能还有另外 8 位。所以我们剩下 32 位 = 4 个字节。
给定一个由 nxn 矩阵表示的图像,其中图像中的每个像素为 4 个字节,编写一个将图像旋转 90 度的方法。 (到位)
我做了一个低效的解决方案,即将每一行复制到一个临时文件,然后执行交换,花费了 o(N) space,下面的实际解决方案更好,但我不明白。
def rotate_matrix(matrix):
'''rotates a matrix 90 degrees clockwise'''
n = len(matrix)
for layer in range(n // 2):
first, last = layer, n - layer - 1
for i in range(first, last):
# save top
top = matrix[layer][i]
# left -> top
matrix[layer][i] = matrix[-i - 1][layer]
# bottom -> left
matrix[-i - 1][layer] = matrix[-layer - 1][-i - 1]
# right -> bottom
matrix[-layer - 1][-i - 1] = matrix[i][- layer - 1]
# top -> right
matrix[i][- layer - 1] = top
return matrix
上面的代码是Python的解决方案,
我不明白 for 循环,为什么它在 n//2 范围内,从第一层到 n-layer-1。
另外,为什么题目提到4个字节好像是无用的信息。
谢谢!
考虑 n
是奇数还是偶数很重要,因为必须以细微不同的方式解决问题。不过,在任何一种情况下,正方形都可以分解为象限。
n
为奇数:
正方形被分解成四个矩形象限。在 double for-loop 的每次迭代中,恰好有 4 个元素被旋转,每个象限一个。永远不会访问中间元素,因为它在旋转中保持在中间。
+-------+---+
| x x | x |
+---+---+ |
| x | x | x |
| +---+---+
| x | x x |
+---+-------+
n
偶数大小写:
矩阵被分解成 4 个正方形象限。同样,在 double for-loop 的每次迭代中,恰好旋转了 4 个元素,每个象限一个。 在偶数情况下,每个元素都必须移动(即没有完美的中心元素)。
+-------+-------+
| x x | x x |
| | |
| x x | x x |
+-------+-------+
| x x | x x |
| | |
| x x | x x |
+-------+-------+
n // 2
和 n - layer - 1
只是变相的下限和上限功能。 n
is odd case 需要 floor 和 ceiling。这些值用于在其中一个象限上设置迭代。然后,对于 一个 象限中存在的许多元素,4 次交换发生在适当的位置(在 top
临时值的帮助下)。
基本上我们通过从矩阵的外边界到内核来旋转元素,顺时针交换项目。
我们以下面的矩阵为例:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
在第一次迭代中我们关心的是外部元素:
1 2 3 4
5 x x 8
9 x x 12
13 14 15 16
我们开始(内循环)顺时针交换所有元素。在我们的示例中,我们将 4(将其存储在临时变量中)替换为 1。之后,我们将 1 替换为 13,依此类推。最后,我们用保存的 4 替换 16。我们继续这样做,直到所有元素都被交换。所以在外循环的第一次迭代之后,我们的数组看起来像这样:
13 9 5 1
14 6 7 2
15 10 11 3
16 12 8 4
之后我们进入下一层。在我们的例子中,我们现在看看:
x x x x
x 6 7 x
x 10 11 x
x x x x
我们再次将所有元素一一交换,如上所示。我们有 floor n/2 次迭代,因为对于不均匀的 n,最后一次迭代给我们留下了一个元素,显然不需要旋转。
这给我们留下了:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
对于像 c 这样我们必须手动管理内存的语言,需要 4 个字节。它们的起源很可能是每个像素由 3 种颜色(红色、绿色和蓝色)组成,并且每种颜色由 8 位(0-255)表示。此外,不透明度可能还有另外 8 位。所以我们剩下 32 位 = 4 个字节。