题目链接

LeetCode

题目描述

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

48. 旋转图像* - 图1

输入: matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出: [[7,4,1],[8,5,2],[9,6,3]]

示例 2:

48. 旋转图像* - 图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]]

示例 3:

输入: matrix = [[1]]
输出: [[1]]

示例 4:

输入: matrix = [[1,2],[3,4]]
输出: [[3,1],[4,2]]

提示:

  • matrix.length == n
  • matrix[i].length == n
  • 1 <= n <= 20
  • -1000 <= matrix[i][j] <= 1000

    解题思路

    方法一:使用辅助数组

    将每一圈先保存,然后再赋值回去。或者直接用一个一样大的数组保存,然后赋值回来

    1. class Solution {
    2. public:
    3. void rotate(vector<vector<int>>& matrix) {
    4. int rows = matrix.size();
    5. if(rows==0)
    6. return;
    7. int cols = matrix[0].size();
    8. int r1=0,c1=0,r2=rows-1,c2=cols-1;
    9. vector<int> tmp(rows*cols,0);
    10. int index = 0,s=0;
    11. while(r1<=r2){
    12. index = 0;
    13. for(int i = c1;i<=c2;++i){
    14. tmp[index++] = matrix[r1][i];
    15. }
    16. for(int i = r1+1;i<=r2;++i){
    17. tmp[index++] = matrix[i][c2];
    18. }
    19. if(r1!=r2){
    20. for(int i = c2-1;i>=c1;--i){
    21. tmp[index++] = matrix[r2][i];
    22. }
    23. }
    24. if(c1!=c2){
    25. for(int i = r2-1;i>r1;--i){
    26. tmp[index++] = matrix[i][c1];
    27. }
    28. }
    29. if(index<2)
    30. break;
    31. s = 0;
    32. for(int i = r1;i<=r2;++i){
    33. matrix[i][c2] = tmp[s++];
    34. }
    35. if(r1!=r2){
    36. for(int i = c2-1;i>=c1;--i){
    37. matrix[r2][i] = tmp[s++];
    38. }
    39. }
    40. if(c1!=c2){
    41. for(int i = r2-1;i>=r1;--i){
    42. matrix[i][c1] = tmp[s++];
    43. }
    44. }
    45. for(int i = c1+1;i<c2;++i){
    46. matrix[r1][i] = tmp[s++];
    47. }
    48. r1++;
    49. c1++;
    50. r2--;
    51. c2--;
    52. }
    53. }
    54. };
  • 时间复杂度 O(n^2)

  • 空间复杂度 O(n)

    方法二:原地旋转

    将矩阵分成四部分,统一进行旋转
    当 n 为偶数时,我们需要枚举 n^2 / 4 = (n/2)×(n/2) 个位置,可以将该图形分为四块,以 4×4 的矩阵为例:

48. 旋转图像* - 图3
当 n 为奇数时,由于中心的位置经过旋转后位置不变,我们需要枚举 (n^2-1) / 4 =((n−1)/2)×((n+1)/2) 个位置,需要换一种划分的方式,以 5×5 的矩阵为例:
48. 旋转图像* - 图4

  1. class Solution {
  2. public:
  3. void rotate(vector<vector<int>>& matrix) {
  4. int n = matrix.size();
  5. if(n<2)
  6. return;
  7. for(int i=0;i<n/2;++i){ //i 代表第几行
  8. for(int j=0;j<(n+1)/2;++j){ //j 代表第几列
  9. // 当 i 固定时,即遍历第 i 行时
  10. int tmp = matrix[i][j];
  11. // matrix[i][j]位置的结果为 i 列从下向上遍历
  12. matrix[i][j] = matrix[n-1-j][i];
  13. // matrix[n-1-j][i]位置的结果为 n-1-i 行从右向左遍历
  14. matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
  15. // matrix[n-1-i][n-1-j]位置的结果为 n-1-i 列从上向下遍历
  16. matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
  17. // matrix[j][n-1-i]位置的结果为 matrix[i][j] 位置的值
  18. // matrix[j][n-1-i]位置的结果为 i 行从左向右遍历
  19. matrix[j][n-1-i] = tmp;
  20. }
  21. }
  22. }
  23. };
  • 时间复杂度 O(n^2)
  • 空间复杂度 O(1)

    方法三:用翻转代替旋转

    先通过水平轴翻转再进行主对角线翻转。
    image.png

    1. class Solution {
    2. public:
    3. void rotate(vector<vector<int>>& matrix) {
    4. int n = matrix.size();
    5. // 水平翻转
    6. for (int i = 0; i < n / 2; ++i) {
    7. for (int j = 0; j < n; ++j) {
    8. swap(matrix[i][j], matrix[n - i - 1][j]);
    9. }
    10. }
    11. // 主对角线翻转
    12. for (int i = 0; i < n; ++i) {
    13. for (int j = 0; j < i; ++j) {
    14. swap(matrix[i][j], matrix[j][i]);
    15. }
    16. }
    17. }
    18. };
    1. class Solution {
    2. public void rotate(int[][] matrix) {
    3. int n = matrix.length;
    4. // 按主对角线交换
    5. for(int i=0;i<n;++i){
    6. for(int j=i+1; j<n;++j){
    7. int tmp = matrix[i][j];
    8. matrix[i][j] = matrix[j][i];
    9. matrix[j][i] = tmp;
    10. }
    11. }
    12. // 按轴对称左右交换
    13. for(int i = 0;i<n/2;++i){
    14. for(int j = 0;j<n;++j){
    15. int tmp = matrix[j][i];
    16. matrix[j][i] = matrix[j][n-i-1];
    17. matrix[j][n-i-1] = tmp;
    18. }
    19. }
    20. }
    21. }
  • 时间复杂度 O(n^2)

  • 空间复杂度 O(1)