Chapter 1 Arrays and Strings - 1.6

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:
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.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章