首页 > 试题广场 >

旋转图像

[编程题]旋转图像
  • 热度指数:12016 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给出一个用二维矩阵表示的图像
返回该图像顺时针旋转90度的结果
扩展:
你能使用原地算法解决这个问题么?

//做两次翻转,先沿右上-左下的对角线翻转,再沿水平中线上下翻转
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        //对角线翻转
        const int n = matrix.size();
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < n - i; j++)
            	swap(matrix[i][j], matrix[n-1-j][n-1-i]);
        for (int i = 0; i < n/2; i++)
            for (int j = 0; j < n; j++)
            	swap(matrix[i][j],matrix[n-1-i][j]);
    }
};

编辑于 2016-09-01 16:43:36 回复(7)
最外圈到最里圈,一层一层的转
关键点:a[ i ][ j ] 这个点下一个位置是: a[ n-1-j ][ i ]
public class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        for(int i=0;i<n/2;i++){
            for(int j=i;j<n-i-1;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;
            }
        }
    }
}

发表于 2018-08-31 16:20:46 回复(2)
//层层旋转
public class Solution {
    public void rotate(int[][] matrix) {
        int n=matrix.length;
        int temp=0;
        for(int i=0;i<n/2;i++){
            for(int j=i;j<n-1-i;j++){
                temp=matrix[i][j];
                matrix[i][j]=matrix[n-j-1][i];
                matrix[n-j-1][i]= matrix[n-i-1][n-j-1];
                matrix[n-i-1][n-j-1]=matrix[j][n-i-1];
                matrix[j][n-i-1]=temp;
            }
        }
      return;
    }
}

发表于 2016-11-06 19:38:10 回复(4)
对于函数中的一个点,先以y=x为轴作对称,然后以x轴作对称,则相当于该点顺时针旋转90°。所以对于图像来说每个点顺时针旋转了,则图也旋转了。所以可以将图以对角线作对称,然后以中间的横线作对称。
发表于 2018-08-17 21:53:27 回复(0)
public class Solution {
    public void rotate(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        int[] arr = new int[row*col];
        int k = 0;
        //将二维数组按顺时针旋转90度的后以从左到右从上到下的顺序访问数组元素并存入一维数组中
        for(int j=0; j < col ;j++){
            for(int i = row-1;i >= 0 ;i--){
                arr[k++] = matrix[i][j];
            }
        }
        int num = 0;
        //按二维数组正常的从左到右从上到下的次序将一维数组赋值给二维数组
        for(int i = 0;i < row ;i++){
            for(int j = 0;j < col;j++){
                 matrix[i][j] = arr[num++];
            }
        }
    }
}

发表于 2019-02-27 16:58:05 回复(2)
```c++
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) 
    {
        int n=matrix.size();
        vector<vector<int>> cop(n,vector<int>(n));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                cop[j][n-i-1]=matrix[i][j];
        matrix=cop;
    }
};
```

发表于 2018-07-14 17:05:51 回复(0)
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        vector<vector<int>> copy=matrix;
        int len=matrix.size();
        for(int i=0;i<len;i++){
            for(int j=0;j<len;j++){
                matrix[j][len-1-i]=copy[i][j];
            }
        }
    }
};

发表于 2018-05-07 16:50:11 回复(0)
/*
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.

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]
]
*/
/*
思路:
先按照y轴交换,再按照主对角线交换
*/
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int rows = matrix.size();
        int cols = matrix[0].size();

        // 按照y轴进行交换
        for (int row = 0; row < rows; ++row) {
            for (int col = 0; col < cols / 2; ++col) {
                swap(matrix[row][col], matrix[row][cols - 1 - col]);
            }
        }

        // 按照主对角线进行交换
        for (int row = 0; row < rows; ++row) {
            for (int col = 0; col < cols - 1 - row; ++col) {
                swap(matrix[row][col], matrix[cols - 1 - col][rows - 1 - row]);
            }
        }
    }
};
发表于 2017-12-02 19:14:24 回复(0)
1.题目要求顺时针旋转90度,那么沿主对角线翻折是顺时针旋转180度,再沿着中间水平线翻折是逆时针旋转90度
2.注意下沿主对角线翻折的处理,a[i][j]的主对角线对称点是a[sz-1-j][sz-1-i];
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
         int sz=matrix.size();
         for(int i=0;i<sz;i++)
             for(int j=0;j<sz-i;j++)
                 swap(matrix[i][j],matrix[sz-1-j][sz-1-i]);
         for(int i=0;i<sz/2;i++)
             for(int j=0;j<sz;j++)
                 swap(matrix[i][j],matrix[sz-1-i][j]);
    }
};

发表于 2017-07-27 21:35:58 回复(0)
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
    	int n = matrix.size();
        for(int i=0;i<n;i++)
        	for(int j=0;j<n-i;j++)
        		swap(matrix[i][j],matrix[n-j-1][n-i-1]);
        
        for(int i=0;i<n/2;i++)
        	for(int j=0;j<n;j++)
        		swap(matrix[i][j],matrix[n-i-1][j]);
    }
};

发表于 2017-07-26 01:18:39 回复(0)
class Solution {
public:
    /// 西安按照主对角线翻转,再每行翻转
    void rotate(vector<vector<int> > &matrix)
    {
        for(int i=0;i<matrix.size();i++)
        {
            for(int j=0;j<=i;j++)
                swap(matrix[i][j],matrix[j][i]);
        }
        for(int i=0;i<matrix.size();i++)
            reverse(matrix[i].begin(),matrix[i].end());
    }
};

发表于 2017-07-14 22:57:26 回复(0)
public class Solution {
    public void rotate(int[][] matrix) {
        int row = matrix.length;
        int column = matrix[0].length;

        for (int i = 0; i < row; i++) {
            for (int j = i + 1; j < column; j++) {
                matrix[i][j] = matrix[i][j] ^ matrix[j][i] ^ (matrix[j][i] = matrix[i][j]);
            }
        }

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < column / 2; j++) {
                matrix[i][j] = matrix[i][j] ^ matrix[i][column - j - 1] ^ (matrix[i][column - j - 1] = matrix[i][j]);
            }
        }
    }
}

发表于 2017-07-04 14:34:14 回复(0)
/*
	 * 交换matrix[i][j]和matrix[j][i]
	 * Runtime: 2 ms
	 */
	public void rotate(int[][] matrix) {
		int n = matrix.length;
		for(int i=0;i<n-1;i++){
			for(int j=i+1;j<n;j++){
				int temp=matrix[i][j];
				matrix[i][j]=matrix[j][i];
				matrix[j][i]=temp;
			}
		}
		
		/*
		 * 左右翻转
		 */
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n/2; j++) {
				int temp = matrix[i][j];
				matrix[i][j] = matrix[i][n-1-j];
				matrix[i][n-1-j] = temp;
			}
		}
	}

	/*
	 * 不推荐的解法 Time:O(n^2) Space:O(n^2) Runtime: 2 ms. Your runtime beats 66.24 %
	 * of java submissions
	 */
	public void rotate_1(int[][] matrix) {
		int n = matrix.length;
		int[][] newMatrix = new int[n][n];

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				newMatrix[j][n - 1 - i] = matrix[i][j];
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++)
				matrix[i][j] = newMatrix[i][j];
		}
	}

发表于 2017-06-25 11:35:47 回复(0)
public class Solution {
    public void rotate(int[][] matrix) {
		int n = matrix.length;
		for (int i = 0; i < n; i ++) {
			for (int j = 0; j < n - i; j ++) {
				matrix[i][j] = matrix[n - 1 - j][n - 1 - i] ^ matrix[i][j] ^ (matrix[n - 1 - j][n - 1 - i] = matrix[i][j]);
			}
		}
		for (int i = 0; i < n / 2; i ++) {
			for (int j = 0; j < n; j ++) {
				matrix[i][j] = matrix[n - 1 - i][j] ^ matrix[i][j] ^ (matrix[n - 1 - i][j] = matrix[i][j]);
			}
		}
	}
}

发表于 2017-03-20 14:02:14 回复(0)
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        const int n = matrix.size();
       
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n - i; j++){
                swap(matrix[i][j], matrix[n-1-j][n-1-i]);
            }
        }
       
        for(int i = 0; i < n / 2; i++){
            for(int j = 0; j < n; j++){
                swap(matrix[i][j], matrix[n-1-i][j]);
            }
        }
    }
};
先沿副对角线翻转一次,再沿水平中线旋转一次即可
发表于 2016-06-28 15:15:21 回复(0)
#include<algorithm>
using namespace std;
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        //do this in-place
        int row = matrix.size();
        int col = matrix[0].size();
        //对矩阵进行转置
        for(int i=0;i<row;i++){
            for(int j=i+1;j<col;j++){
                //交换
                matrix[i][j] = matrix[i][j]^matrix[j][i];
                matrix[j][i] = matrix[i][j]^matrix[j][i];
                matrix[i][j] = matrix[i][j]^matrix[j][i];
            }
        }
        //得到的矩阵与原矩阵顺时针旋转90度的矩阵成镜像对称
        for(int i=0;i<row;i++){
            //reverse(matrix[i].begin(),matrix[i].end());
            //自己实现翻转
            int half = col>>1;
            for(int j=0;j<half;j++){
                matrix[i][j] = matrix[i][j]^matrix[i][col-1-j];
                matrix[i][col-1-j] = matrix[i][j]^matrix[i][col-1-j];
                matrix[i][j] = matrix[i][j]^matrix[i][col-1-j];
            }
        }
    }
};

发表于 2016-06-25 15:08:52 回复(0)
class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {//把行转化为列
        vector<vector<int> > C(matrix[0].size(),vector<int>(matrix.size()));//定义一个新矩阵
        int i=0,j=0;//指针初始化
        while(i<=matrix.size()-1){
            for(j=0;j<=matrix[0].size()-1;j++){C[j][matrix.size()-i-1]=matrix[i][j];}
            i++;
        }
        matrix=C;
    }
};
发表于 2021-11-12 04:43:30 回复(0)
//注意调节好参数,不然就错一个数字也要调试好久
//因为旋转矩阵的时候如果仅交换两个值会有覆盖现象
//所以从容易理解的逻辑出发,需要额外存储空间暂存值,运行时间57ms空间11372k
    public void rotate(int[][] matrix) {

        int[] arr = new int[matrix.length];  //存矩形的上边(上面行)
        int[] arr1 = new int[matrix.length];  //存矩形的右边
        if (matrix.length == 1) {
            return;
        }
//       看作多个嵌套旋转的四边框,左上角坐标(i,i)
        for (int i = 0; i <= (matrix.length - 1) / 2; i++) {
             if((i==(matrix.length - 1) / 2)&&(matrix.length%2>0)){
                 break;
             }
//            储存上面行
            int count = 0;
            int nailIndex = matrix.length - 1 - i;
            for (int up = i; up <= nailIndex; up++) {
                arr[count] = matrix[i][up];
                count++;
            }
//            储存右边行
            int count1 = 0;
            for (int rightIn = i; rightIn <= nailIndex; rightIn++) {
                arr1[count1] = matrix[rightIn][nailIndex];
                count1++;
            }
//            左行盖上面行
            int leftTemp=i;
            for (int left = nailIndex; left >= i; left--) {
                matrix[i][left] = matrix[leftTemp][i];
                leftTemp++;
            }
//            下面换到左边
            for (int down = i; down <= nailIndex; down++) {
                matrix[down][i] = matrix[nailIndex][down];
            }
//            储存的上边行覆盖右边行
            count = 0;
            for (int rightSav = i ; rightSav <= nailIndex; rightSav++) {
                matrix[rightSav][nailIndex] = arr[count];
                count++;
            }
//            存储的右边换到下面
            count1 = 0;
            for (int right = nailIndex; right >=i; right--) {
                matrix[nailIndex][right]=arr1[count1];
                count1++;
            }
        }
    }

编辑于 2020-09-24 17:48:49 回复(0)

这一问题可以有如下问法(都是空间复杂度为常数级别):

  1. 矩阵左旋/右旋90度
  2. 矩阵左旋/右旋180度

对于本题,有两种思路:

思路一:利用对称进行旋转——先根据主对角线互换元素,再根据垂直中线互换元素

图片说明

思路二:利用坐标映射

图片说明

强烈建议用第一种方法,因为找第二种方法的坐标关系特别特别特别麻烦

举一反三:面对旋转、填充一类的题型,一定要考虑对称这一“大杀器”,它能极大的减少工作量,提高解题正确率和解题效率

思路一的代码

//
// Created by jt on 2020/9/5.
//
#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        int n = matrix.size();
        // 按主对角线反转
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                swap(matrix[i][j], matrix[j][i]);
            }
        }
        // 左右反转
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n / 2; ++j) {
                swap(matrix[i][j], matrix[i][n-1-j]);
            }
        }

    }
};

思路二的代码

//
// Created by jt on 2020/9/5.
//
#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        int n = matrix.size();
        for (int i = 0; i < n / 2; ++i) {
            int m = n - 2 * i;
            for (int j = i; j < i + m - 1; ++j) {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[2*i-j+m-1][i];
                matrix[2*i-j+m-1][i] = matrix[i+m-1][2*i-j+m-1];
                matrix[i+m-1][2*i-j+m-1] = matrix[j][i+m-1];
                matrix[j][i+m-1] = tmp;
            }
        }
    }
};
发表于 2020-09-05 18:03:42 回复(0)
首先找到旋转前后对应关系,即第i行,j列的P(i,j)会旋转到哪个位置。首先说结论,会旋转到(j,n - 1 - i)。推导如下,
矩阵坐标是以左上角(0,0)为原点的,而旋转其实是以矩阵中心为原点的,因此,先确定矩阵中(i,j)在以矩阵中心为原点的坐标(j -  n/2,  n/2 -i, ),然后对其顺时针旋转90°,旋转矩阵为[cos-90,-sin-90;sin-90,cos-90]。
即[0,1;-1,0],则原始坐标(i,j) --->矩阵中心为原点坐标 (  j - n/2, n/2 - i)  ---->旋转后矩阵中心为原点坐标(n/2 - i,  n/2 - j)--->以左上角为原点(j,  n-1-i)。
所以可以先沿在主对角线翻转得到【j,i】,然后左右翻转即可
发表于 2020-08-14 01:08:37 回复(0)