zoukankan      html  css  js  c++  java
  • LeetCode第[48]题(Java):Rotate Image

    题目:矩阵旋转

    难度:Medium

    题目内容

    You are given an n x n 2D matrix representing an image.

    Rotate the image by 90 degrees (clockwise).

    Note:

    You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.

    翻译:你有一个n*n 的2D矩阵表示一个图像。

    将图像旋转90度(顺时针)。

    注意:

    你必须在原地旋转图像,这意味着你必须直接修改输入2D矩阵。不要分配另一个2D矩阵并进行旋转。

    Example 1:

    Given input matrix = 
    [
      [1,2,3],
      [4,5,6],
      [7,8,9]
    ],
    
    rotate the input matrix in-place such that it becomes:
    [
      [7,4,1],
      [8,5,2],
      [9,6,3]
    ]
    

    Example 2:

    Given input matrix =
    [
      [ 5, 1, 9,11],
      [ 2, 4, 8,10],
      [13, 3, 6, 7],
      [15,14,12,16]
    ], 
    
    rotate the input matrix in-place such that it becomes:
    [
      [15,13, 2, 5],
      [14, 3, 4, 1],
      [12, 6, 8, 9],
      [16, 7,10,11]
    ]
     

    我的思路:旋转90°,那就是把矩阵分为四块,只对第一块进行循环,然后用第一块的元素下标【i】【j】的表达式分别表示其他块的对应元素,然后把四个元素进行交换即可

    先将矩阵分为如下四块:

    A B

    C D

    现在对A内元素进行循环,其元素下标表示为【i】【j】

    1、将A的此元素用temp存储起来,

    2、A的此元素取C区域对应的元素值,C区对应元素表示为A元素“先关于矩阵主对角线取对称,然后再取纵向中心对折”

      主对角线取对称,就是【i】【j】=》【j】【i】

      纵向中心对折,就是【i】【j】=》【n-1- i 】【j】  

    3、C区此元素取D区域对应的元素值,D区对应元素表示为A元素的中心对称,即“先关于横向中心对折,然后再取纵向中心对折”

      横线中心对折,就是【i】【j】=》【i】【n-1- j】

     4、D区此元素取B区域对应的元素值,B区对应元素表示为A元素“先关于横向中心对折,然后再取矩阵副对角线对称”

      副对角线对称,就是【i】【j】=》【n-1-j】【n-1-i】

     5、B区此元素取之前A区的值,即为 temp ,到此一轮交换结束。

    需要注意的是,当矩阵的大小是偶数的时候,此时行数的对称中心 x 为对称线的上面的一个。

    例如:

    0

    1

    2

    3   此时的 x = n-1 = 1,此时是需要进行交换的行范围是【0~x】,列范围也是【0~x】

      而如果是奇数,则行范围是【0~x-1】,列范围没变还是【0~x】

    所以循环的时候需要注意判断奇偶,然后跳过。

    我的代码

     1     public void rotate(int[][] matrix) {
     2         int n = matrix.length;
     3         if (n <= 1) {
     4             return;
     5         }
     6         
     7         int even = 1;
     8         if (matrix.length % 2 == 1) {
     9             even = 0;
    10         }
    11         
    12         int x = (n-1)/2;
    13         for (int i = 0; i <= x; i++) {
    14             for (int j = 0; j <= x; j++) {
    15                 if (even==0 && i==x) {
    16                     continue;
    17                 }
    18                 int temp = matrix[i][j];
    19                 matrix[i][j] = matrix[n-1-j][i];
    20                 matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
    21                 matrix[n-1-i][n-1-j] = matrix[n-1-(n-1-j)][n-1-i];
    22                 matrix[n-1-(n-1-j)][n-1-i] = temp;
    23             }
    24         }
    25     }

    我的复杂度:O(N2

    编码过程中的问题

     1、应该使用A的元素下标【i】【j】去表示其他块所有,而不是用相对位置;

     2、对“对称”“对折”的下标变化不熟悉,导致浪费不少时间;(还想了半天用 2x - i + even 来表示,其实直接 n-1-i 即可)

     3、之前没考虑到矩阵奇偶对循环范围的影响,导致奇数的对称线没有交换;

     4、当方法定义返回为void的时候,需要直接返回,写return就行。

    答案代码

     1     public void rotate(int[][] matrix) {
     2         int n = matrix.length;
     3         if (n <= 1) {
     4             return;
     5         }
     6         
     7         int x = (n-1)/2;
     8         for (int i = 0; i <= x; i++) {
     9             int[] tmp = matrix[i];
    10             matrix[i] = matrix[n-1-i];
    11             matrix[n-1-i] = tmp;
    12         }
    13         
    14         for (int i = 0; i < n; i++) {
    15             for (int j = i+1; j < n; j++) {
    16                 int temp = matrix[i][j];
    17                 matrix[i][j] = matrix[j][i];
    18                 matrix[j][i] = temp;
    19             }
    20         }
    21     }

    答案复杂度:O(N2

    答案思路

    首先将整个数组上下对称交换

    1 2 3     7 8 9 
    4 5 6  => 4 5 6
    7 8 9     1 2 3

    然后再关于主对角线对称交换

    7 8 9     7 4 1
    4 5 6  => 8 5 2
    1 2 3     9 6 3

    优点:逻辑清晰明了

    缺点:复杂度比我的方法高一点

     

    扩展

     逆时针旋转90°?

    我的方法——ABCD块之间的取值关系会发生变化。

    答案方法——有两种修改方法都行:

          a:第一步和第二步交换,即先对角线,后对折

          b:把第一步的上下对称交换改成左右对称交换,第二步不变。

  • 相关阅读:
    ubuntu 安装 redis desktop manager
    ubuntu 升级内核
    Ubuntu 内核升级,导致无法正常启动
    spring mvc 上传文件,但是接收到文件后发现文件变大,且文件打不开(multipartfile)
    angular5 open modal
    POJ 1426 Find the Multiple(二维DP)
    POJ 3093 Margritas
    POJ 3260 The Fewest Coins
    POJ 1837 Balance(二维DP)
    POJ 1337 A Lazy Worker
  • 原文地址:https://www.cnblogs.com/Xieyang-blog/p/9015493.html
Copyright © 2011-2022 走看看