微软面试题: LeetCode 48. 旋转图像 出现次数:3

题目描述:

  给定一个 × n 的二维矩阵表示一个图像。将图像顺时针旋转 90 度。要求空间 O( 1 )

分析:

  要求空间 O(1)  意味着必须在给定的 矩阵内通过交换元素的方式原地旋转矩阵。

第一步:分层

总体思路就是 对矩阵从外到内分层(如下图),从最外层环到最内层环逐层旋转。比如 5*5 矩阵可以分成下面的 3层。

 

 第二步:4 个边角点坐标表示一环层的元素 

   每一环层都可以用左上、右上、左下、右下 的 4个边角点表示环层内所有元素。由于是 n * n 矩阵,

可以定义两个变量p1, p2 表示 4个边角点,从最外环层开始,初始化  int p1 = 0,p2 = n - 1  四个边角点 

左上(p1,p1)、右上(p1,p2)、左下(p2,p1)、右下 (p2,p2)。

 

 

 

第三步:旋转每一环层

  旋转的时候每 4 个对称的节点,进行交换操作,交换中需要用到一个临时变量。

如下图,对同一种颜色的数字,可以先用一个 临时变量  tmp 保存数字 1 位置的元素,

由于是 顺时针旋转 90度,将 位置 4 的元素移到 位置 1,将  位置 3 的元素移到位置 4,

将位置 2 的元素移到位置 3,将保存在 tmp 中的原位置 1 上的元素 移到位置 2。

待图上所有颜色的数字对应的位置都移动完成后,则当前层旋转完成,接着旋转里面一层的元素。

  如下图,第一次旋转红色数字,第二次旋转黄色数字,第三次旋转蓝色数字,第四次旋转紫色数字。

可以看出,每次旋转的时候比上一次旋转偏移了一格。第一次旋转的四个点坐标分别为

左上(p1,p1)、右上(p1,p2)、左下(p2,p1)、右下 (p2,p2)。更一般地表达,对左上(p1,p1 +add)、

右上(p1+add,p2)、左下(p2-add,p1)、右下 (p2,p2-add)。当add = 0 表示第一次旋转,1 表示第二次旋转,

2 表示 第三次旋转,3表示第四次旋转。add >= 0 且 add + p1 < p2 。

 

 

 第四步:每次计算完一层之后,矩阵向内收缩一层,如图所示:

 

   经坐标变换:pos1 = pos1+1,pos2 = pos2-1 。四个边角点仍可表示为 左上(p1,p1)、

右上(p1,p2)、左下(p2,p1)、右下 (p2,p2)。矩阵收缩到最里面一层终止,终止条件:pos1 < pos2。

 

最终代码如下所示:

 

 1 class Solution {
 2 public:
 3     void rotate(vector<vector<int>>& matrix) 
 4     {
 5         int pos1 = 0,pos2 = matrix.size() - 1;
 6         while(pos1 < pos2) //外层矩环 -> 内层矩环
 7         {
 8             int add = 0;
 9             while(add < pos2 - pos1) 
10             {
11                 int tmp = matrix[pos2-add][pos1];
12                 matrix[pos2-add][pos1] = matrix[pos2][pos2-add];
13                 matrix[pos2][pos2-add] = matrix[pos1+add][pos2];
14                 matrix[pos1+add][pos2] = matrix[pos1][pos1+add];
15                 matrix[pos1][pos1+add] = tmp;
16                 ++add;
17             }
18             pos1 = pos1 + 1;
19             pos2 = pos2 - 1;
20         }
21         return;
22     }
23 };

 

posted @ 2020-11-18 00:05  谁在写西加加  阅读(150)  评论(0编辑  收藏  举报