在数组操作练习中支持的常见问题是将二维数组旋转90度。有一些SO帖子可以解答如何在各种编程语言中完成它。我的问题是澄清其中的一个答案,并探讨需要什么样的思维过程才能以有机的方式得出答案。
我发现这个问题的解决方案如下:
public static void rotate(int[][] matrix,int n)
{
for( layer = 0;layer < n/2;++layer){
int first = layer;
int last = n -1 - layer;
for(int i = first;i<last;++i){
int offset = i - first;
int top = matrix[first][i];
matrix[first][i] = matrix[last-offset][first];
matrix[last-offset][first] = matrix[last][last-offset];
matrix[last][last-offset] = matrix[i][last];
matrix[i][last] = top;
}
}
}
我对上面的代码试图做什么有点了解,它通过进行四向交换来交换四肢/角落,并对由一些偏移量分隔的其他单元格做同样的事情。
单步执行此代码我知道它有效,我得不到的是上面给出的算法的数学基础。 “层”,“第一”,“最后”和偏移背后的基本原理是什么?
'last'结果如何成为n-1-layer
?为什么偏移i-first
?首先是什么偏移?
如果有人能解释这个算法的起源并引导我完成思考过程以提出解决方案,那就太棒了。
由于
答案 0 :(得分:6)
我们的想法是将大任务(旋转方阵)分解为更小的任务。
首先,方形矩阵可以分解为同心方形环。环的旋转独立于其他环的旋转,因此旋转矩阵只是逐个旋转每个环。在这种情况下,我们从最外圈开始向内工作。我们使用layer
(或first
,同样的事情)对戒指进行计数,并在我们到达中间时停止,这就是它升至n/2
的原因。 (值得检查以确保这适用于奇数和偶数n
。)使用last = n - 1 - layer
跟踪环的“远边”非常有用。例如,在5x5矩阵中,第一个环从first=0
开始,到last=4
结束,第二个环从first=1
开始,到last=3
结束,依此类推。 / p>
如何旋转戒指?沿着顶部边缘向上走,沿着左边缘向上走,沿着底部边缘向左走,沿着右边缘向下走,所有这些都是同时进行的。在每个步骤交换四个值。更改的坐标为i
,步数为offset
。例如,在第二个环上走动时,i
转为{1,2,3},offset
转为{0,1,2}。