我正在研究旋转NxN矩阵的这段代码;我已无数次追踪该程序,我有点理解实际旋转是如何发生的。它基本上首先旋转角落,然后沿角落顺时针旋转角落后的元素。我只是不理解几行,而且我的大脑中的代码仍然没有“驱动回家”,可以这么说。请帮忙。我将它旋转90度,给出一个4x4矩阵作为我的跟踪示例。
[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]
变为
[3][9][5][1]
[4][0][6][2]
[5][1][7][3]
[6][2][8][4]
public static void rotate(int[][] matrix, int n){
for(int layer=0; layer < n/2; ++layer) {
int first=layer; //It moves from the outside in.
int last=n-1-layer; //<--This I do not understand
for(int i=first; i<last;++i){
int offset=i-first; //<--A bit confusing for me
//save the top left of the matrix
int top = matrix[first][i];
//shift left to top;
matrix[first][i]=matrix[last-offset][first];
/*I understand that it needs
last-offset so that it will go up the column in the matrix,
and first signifies it's in the first column*/
//shift bottom to left
matrix[last-offset][first]=matrix[last][last-offset];
/*I understand that it needs
last-offset so that the number decreases and it may go up the column (first
last-offset) and left (latter). */
//shift right to bottom
matrix[last][last-offset]=matrix[i][last];
/*I understand that it i so that in the next iteration, it moves down
the column*/
//rightmost top corner
matrix[i][last]=top;
}
}
}
答案 0 :(得分:9)
如果你绘制一个图表,那么理解这样的算法会更容易,所以我在Paint中制作了一张快速图片来演示5x5矩阵:D
外部for(int layer=0; layer < n/2; ++layer)
循环从外到内迭代各层。外层(层0)由有色元素描绘。每层实际上是需要旋转的元素的正方形。对于n = 5, layer 将取0到1的值,因为我们可以忽略不受旋转影响的中心元素/图层。 first 和 last 指的是图层元素的第一行和最后一行/列;例如第0层包含从行/列第一个= 0 到最后= 4 的元素和从行/第1列到第3行的第1层。
然后对于每个图层/正方形,内部for(int i=first; i<last;++i)
循环通过在每次迭代中旋转4个元素来旋转它。 偏移表示我们所在广场两侧的距离。对于我们下面的5x5,我们首先旋转红色元素(偏移= 0),然后是黄色(偏移= 1),然后是绿色和蓝色。箭头1-5表示红色元素的4元素旋转,其余6 +元素以相同的方式执行。注意4元素旋转本质上是一个5指派循环交换,第一个赋值暂时放在一个元素旁边。此分配的//save the top left of the matrix
注释具有误导性,因为矩阵[first] [i]不一定是矩阵的左上角,甚至不一定是该层的左上角。另请注意,旋转元素的行/列索引有时与 offset 成比例,有时与其反向成比例, last - offset 。
我们以这种方式沿着外层的两侧移动(由first = 0和last = 4描绘),然后移动到内层(first = 1和last = 3)并在那里做同样的事情。最终,我们击中了中心,我们已经完成了。
答案 1 :(得分:6)
这会触发WTF。旋转矩阵的最简单方法是
当矩阵是列专用时,第二个操作是交换列,因此具有良好的数据局部性属性。如果矩阵是行主,那么首先置换行,然后转置。
答案 2 :(得分:0)
以下是解决此问题的递归方法:
//将2 D阵列(mXn)旋转90度
public void rotateArray(int[][] inputArray) {
System.out.println("Input Array: ");
print2D(inputArray);
rotateArray(inputArray, 0, 0, inputArray.length - 1,
inputArray[0].length - 1);
System.out.println("\n\nOutput Array: ");
print2D(inputArray);
}
public void rotateArray(int[][] inputArray, int currentRow,
int currentColumn, int lastRow, int lastColumn) {
// condition to come out of recursion.
// if all rows are covered or all columns are covered (all layers
// covered)
if (currentRow >= lastRow || currentColumn >= lastColumn)
return;
// rotating the corner elements first
int top = inputArray[currentRow][currentColumn];
inputArray[currentRow][currentColumn] = inputArray[lastRow][currentColumn];
inputArray[lastRow][currentColumn] = inputArray[lastRow][lastColumn];
inputArray[lastRow][lastColumn] = inputArray[currentRow][lastColumn];
inputArray[currentRow][lastColumn] = top;
// clockwise rotation of remaining elements in the current layer
for (int i = currentColumn + 1; i < lastColumn; i++) {
int temp = inputArray[currentRow][i];
inputArray[currentRow][i] = inputArray[lastRow - i][currentColumn];
inputArray[lastRow - i][currentColumn] = inputArray[lastRow][lastColumn
- i];
inputArray[lastRow][lastColumn - i] = inputArray[currentRow + i][lastColumn];
inputArray[currentRow + i][lastColumn] = temp;
}
// call recursion on remaining layers
rotateArray(inputArray, ++currentRow, ++currentColumn, --lastRow,
--lastColumn);
}