Tuesday, September 3, 2013

1.6 ---- rotate the matrix

Q:
 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?

A:
 
public class Main {

 public static void main(String[] args) {

  int imSize = 6;

  int[][] image = new int[imSize][imSize];
  // Initialize image
  Tool.randomInitializeArray(image);
  Tool.printArray(image);

  rotateImage90(image);

  Tool.printArray(image);
 }

 public static void rotateImage90(int[][] im) {

  // rotate the matrix in place, clock wise direction of 90 degree
  int numRow = im.length;
  int numCol = im[1].length;

  // check they are square matrix
  if (numRow != numCol) {
   System.out.println("not square matrix");
  }
  if (numRow == 0) { // actually, this could be ignored.
   System.out.println("no elements");
  }
  int imSize = numRow;
  if (imSize % 2 == 1) {
   // if imSize is odd number, rotate from the most inner circle ( of
   // size 1*1)
   int centerIndex = (int) (numRow / 2) + 1; // in math, this is the
              // center point.
   centerIndex = centerIndex - 1; // because java starts array index
           // from zero, we need minus 1
   int radius = (int) (numRow / 2);
   for (int d = 1; d <= radius; d++) {
    // there are four lines per circle. we rotate them
    // one-by-one
    int lineLength = 2 * d;
    int[] tmpLine = new int[lineLength];
    // save the line above to tempArray
    for (int i = -d + 1; i <= d; i++)
     // ignore the left most vertex
     tmpLine[i - (-d + 1)] = im[centerIndex - d][centerIndex + i];

    // copy left to above
    for (int i = -d + 1; i <= d; i++)
     im[centerIndex - d][centerIndex + i] = im[centerIndex - i][centerIndex
       - d];

    // copy below to left
    for (int i = -d + 1; i <= d; i++)
     im[centerIndex - i][centerIndex - d] = im[centerIndex + d][centerIndex
       - i];

    // copy right to below
    for (int i = -d + 1; i <= d; i++)
     im[centerIndex + d][centerIndex - i] = im[centerIndex + i][centerIndex
       + d];

    // copy original above(now in tmpLine) to right
    for (int i = -d + 1; i <= d; i++)
     im[centerIndex + i][centerIndex + d] = tmpLine[i - (-d + 1)];
   }
  } else { // imSize is even number, i.e. , imSize == 2, 4 , 6, 8....
   int indexLeftTop = (int) (imSize / 2) - 1;
   int indexRightBottom = (int) (imSize / 2);
   int radius = (int) (imSize / 2);
   // because by considering
   System.out.println("we are working on the array, sized == "
     + imSize);
   for (int d = 1; d <= radius; d++) { // for each layer,with distance
            // to center is d
    int lineLength = indexRightBottom - indexLeftTop;
    int tmpLine[] = new int[lineLength];
    // save the above circle into the tmpLine ( do not include the
    // topLeft corner
    for (int i = 1; i <= lineLength; i++) {
     tmpLine[i - 1] = im[indexLeftTop][indexLeftTop + i];
    }
    // transfer the left into above
    for (int i = 1; i <= lineLength; i++) {
     im[indexLeftTop][indexLeftTop + i] = im[indexRightBottom
       - i][indexLeftTop];
    }
    // transfer the bottom into left
    for (int i = 1; i <= lineLength; i++) {
     im[indexRightBottom - i][indexLeftTop] = im[indexRightBottom][indexRightBottom
       - i];
    }

    // transfer the right into the bottom
    for (int i = 1; i <= lineLength; i++) {
     im[indexRightBottom][indexRightBottom - i] = im[indexLeftTop
       + i][indexRightBottom];
    }

    // transfer the saved,original above line into the right
    for (int i = 1; i <= lineLength; i++) {
     im[indexLeftTop + i][indexRightBottom] = tmpLine[i - 1];
    }
    indexLeftTop--;
    indexRightBottom++;
   }// end of the for, for each layer, from inner most to the outer
    // most

  } // end of else, for the case that the length is even number
 } // end of function rotateImage90
}
Mistakes:
0:  FUCK!!!!!!!!!!!
因为在rotate完毕,要打印数组的时候,是直接从上面copy的两个for loop,其中,就包含了一行 image[i][j] 的初始化代码。。我日阿
        以后再copy代码的时候,一定要注意,先看看代码里都是什么。(即使是自己写 的)
 
1: 遇到数组溢出。 问题出在
int centerIndex = (int)(numRow/2) + 1;
        int radius =  (int)(numRow/2)+1;  //这里,的radius是从上面一行copy下来的。
而应该自己写, 就不会加上这个 1 了。----------哎,人生阿

2: 遇到数组问题,  毛病出在。

  自己作运算的时候, 都是按照数学里的start from 1, 来计算,安排的。
可是,java中是start from 0.   ------------>  刚开始的时候,还记得,但是,直接写index的时候,就忘了。

3:for odd number, for each line, to copy and rotate into another line, 应该记住,一条边,随说是包括两边顶点。 但rotate的时候,只需要一个顶点就够了

            for(int i = -d; i<=d;i++) ------------------------这是错误的
            for(int i = -d; i<d;i++) ------------------------这是正确的。

 4:对于数组
a b c
d e f
g h i

如果按照上面的rotate算法,[a; d] 应该是 取代[ b c ] 的位置。
而不是,[ d ; g] 取代 [a b]的位置。
因此:我的初始代码中
  int imSize  = numRow;
  // if imSize is odd number,  rotate from the most inner circle ( of size 1*1)
  int centerIndex = (int)(numRow/2) + 1;  // mathetically, this is the center point. 
  centerIndex = centerIndex -1;       // because java starts array index from zero, we need minus 1
  int radius =  (int)(numRow/2);
  for (int d = 1; d <= radius; d++){
   // there are four lines for each circle.  we just rotate them one-by-one
   int lineLength = 1+2*d;
   int[] tmpLine = new int[lineLength];
   // save the line above to tempArray
   for(int i = -d; i
是错误的, 是假设了[ d ; g] 取代 [a b]的位置。 5: 对于,矩形边是偶数的时候 , 在rotate完了每一圈之后,  忘了update indexLeftTop 和indexRightBottom的值了。

No comments:

Post a Comment