zoukankan      html  css  js  c++  java
  • LeetCode Notes_面试题 01.07. 旋转矩阵

    LeetCode Notes_面试题 01.07. 旋转矩阵

    Contents

    题目

    给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。
    不占用额外内存空间能否做到?
    示例 1:

    给定 matrix = 
    [
      [1,2,3],
      [4,5,6],
      [7,8,9]
    ],
    
    原地旋转输入矩阵,使其变为:
    [
      [7,4,1],
      [8,5,2],
      [9,6,3]
    ]

    示例 2:

    给定 matrix =
    [
      [ 5, 1, 9,11],
      [ 2, 4, 8,10],
      [13, 3, 6, 7],
      [15,14,12,16]
    ], 
    
    原地旋转输入矩阵,使其变为:
    [
      [15,13, 2, 5],
      [14, 3, 4, 1],
      [12, 6, 8, 9],
      [16, 7,10,11]
    ]

    解答

    方法1:使用额外空间

    创建一个新的矩阵newMatrix,按照旋转90度的方式把原矩阵的每个元素放入新矩阵。
    在纸上写出新旧矩阵元素坐标,不难发现坐标的对应关系,

    newMatrix[j][n - 1 - i] = matrix[i][j];

    注意,本题给出的函数签名没有返回值,所以还需要将newMatrix赋值回原矩阵。

    class Solution {
        public void rotate(int[][] matrix) {
            int n = matrix.length;
            int[][] newMatrix = new int[n][n];
            for(int i = 0;i <= n - 1;i++){
                for(int j = 0;j <= n - 1;j++){
                    newMatrix[j][n - 1 - i] = matrix[i][j];
                }
            }
            for(int i = 0;i <= n - 1;i++){
                for(int j = 0;j <= n - 1;j++){
                    matrix[i][j] = newMatrix[i][j];
                }
            } 
        }
    }

    复杂度分析

    时间复杂度:O(n2)
    空间复杂度:O(n2)

    方法2:先转置,再对每行中点翻转

    分为两个步骤,代码看上去会很清晰。

    1. 首先沿着左上-右下对角线进行翻转,其实就相当于矩阵的转置。转置过后,变成了这样:
        [1,4,7]             [7,4,1]
        [2,5,8] --------->  [2,5,8](观察发现,还需要左右对称翻转)
        [3,6,9]             [3,6,9]
    1. 观察转置之后的矩阵和目标矩阵的差距,如上,可以发现我们再进行一次左右对称的翻转,就可以得到目标矩阵了。
        [7,4,1]
        [8,5,2]
        [9,6,3]
    class Solution {
        public void rotate(int[][] matrix) {
            int n = matrix.length;
            for(int i = 0;i <= n - 1;i++){
                for(int j = i + 1;j <= n - 1;j++){
                    int temp = matrix[i][j];
                    matrix[i][j] = matrix[j][i];
                    matrix[j][i] = temp;
                }
            }
            //位运算右移一位,其实就是除以2的意思
            int mid = n >> 1;
            for(int i = 0;i <= n - 1;i++){
                //这里的循环边界条件,一定要在纸上举例子验证,很容易搞错
                for(int j = 0;j <= mid - 1;j++){
                    int temp = matrix[i][j];
                    matrix[i][j] = matrix[i][n - 1 - j];
                    matrix[i][n - 1 - j] = temp;
                }
            }
        }
    }

    复杂度分析

    时间复杂度:O(n2)
    空间复杂度:O(1),没有借助额外变量

    方法3: 矩阵分为四块并进行顺时针旋转

    这个方法比较抽象,但是理解之后,代码写起来很简单。以下有一个很清晰的图解。

    1. 首先我们可以将整个矩阵分解为四块,即左上,右上,左下,右下。我们发现其实旋转90度时,这四块当中的对应元素(也就是图中颜色相同的元素)进行了一次旋转。
    2. 然后我们可以观察出这些对应元素之间的坐标关系
    • 左上角元素坐标(i,j)
    • 右上角元素坐标(j, n - 1 - i)
    • 右下角元素坐标(n - 1 - i, n - 1- j)
    • 左下角元素坐标(n - 1 - j, i)


    需要注意的是矩阵行列数为奇数的情况,左上角区域并不是整个矩阵的四分之一。


    class Solution {
        public void rotate(int[][] matrix) {
            int n = matrix.length;
            for(int i = 0;i < n / 2;i++){
                for(int j = 0;j < (n + 1) / 2;j++){
                    int temp = matrix[i][j];
                    matrix[i][j] = matrix[n - 1 - j][i];
                    matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j];
                    matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i];
                    matrix[j][n - 1 - i] = temp;
                }
            }
        }
    }

    复杂度分析

    时间复杂度:O(n2)
    空间复杂度:O(1),没有借助额外变量

  • 相关阅读:
    performance lazy-initialization
    Blazor项目文件分析
    Ubuntu 16.04重启Nautilus
    Ubuntu下查看APT安装的软件安装路径和版本
    Ubuntu 16.04搭建原始Git服务器
    Java原始封装常用HttpRequest
    CentOS 5/6安装后的必备设置(转)
    CentOS通过日志反查入侵(转)
    CentOS下防御或减轻DDoS攻击方法(转)
    通过LoadBalancerClient获取所有服务列表的IP
  • 原文地址:https://www.cnblogs.com/Howfars/p/13758051.html
Copyright © 2011-2022 走看看