Problem 1.6: Given an image represented by an NxN matrix, where each pixel in the image is 4 bytes, write a method to rotate the image by 90 degrees. Can you do this in place?
The question is not clear. The interviewer should specify by which direction the matrix should be rotated (clockwise or counter-clockwise). I will rotate it clockwise by 90 degrees.
Do it by copying is quite easy:
For the in place requirement, I came up with a smart solution quickly (by drawing some instances on the paper). In my solution, I divide a matrix into several circles (rectangles) and each circle can rotate independently. The rotation of a circle can be simplified to rotation of several pixels on this circle and the rotation of other pixels will be driven by rotation of these pixels. So I successfully reduce the problem to rotation of one pixel in place, which seems easy enough.
My solution is similar to the standard one. Dividing the problem into sub problems is a great strategy!
It took me more than one hour to implment rotate_pixel because it's not as easy as I thought before. Pay attention to
The question is not clear. The interviewer should specify by which direction the matrix should be rotated (clockwise or counter-clockwise). I will rotate it clockwise by 90 degrees.
Do it by copying is quite easy:
def rotate_90degree(M, N):
M_new = [[0 for j in range(0, N)] for i in range(0, N)]
for i in range(0, N):
for j in range(0, N):
M_new[j][N-i-1] = M[i][j]
return M_new
For the in place requirement, I came up with a smart solution quickly (by drawing some instances on the paper). In my solution, I divide a matrix into several circles (rectangles) and each circle can rotate independently. The rotation of a circle can be simplified to rotation of several pixels on this circle and the rotation of other pixels will be driven by rotation of these pixels. So I successfully reduce the problem to rotation of one pixel in place, which seems easy enough.
My solution is similar to the standard one. Dividing the problem into sub problems is a great strategy!
def rotate_90degree_inplace(M, N):
last_circle = 0
if N%2 == 0:
last_circle = int(N/2)
else:
last_circle = int(N/2) - 1
# From outermost to center, rotate each circle of elements
for i in range(0, last_circle):
rotate_circle(i, M, N)
def rotate_circle(i, M, N):
# Rotate each element on the circle.
# Only a part of the elements on the circle should be
# rotated and the rotation of other elements will be driven by them
for j in range(i, N-i-1):
rotate_pixel(i, j, M, N)
def rotate_pixel(i, j, M, N):
print "Rotate pixel: ", i, j
# Note that the rotation of one element will
# drive another 3 elements on the same circle to rotate.
# Swap the four elements
indices = []
elements = []
for k in range(0, 4):
indices.append((i, j))
elements.append(M[i][j])
i, j = j, N-i-1
M[indices[0][0]][indices[0][1]] = elements[3]
for k in range(1, 4):
M[indices[k][0]][indices[k][1]] = elements[k-1]
It took me more than one hour to implment rotate_pixel because it's not as easy as I thought before. Pay attention to
i, j = j, N-i-1
because it is different from
i = j
j = N-i-1
The later one is equivalent to
i = j
j = N-j-1
which caused a bug in my first version of implementation.