面试题旋转矩阵(两种方法分析及扩展)

【纯C】旋转矩阵

Day1-旋转矩阵-
(没记错的话这道题在鹅厂面试校招的时候考过)

给你一幅由 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]
]

解法一

辅助数组
看到这道题给我最直观的思路是新建一个与原矩阵相同大小的临时矩阵,将图像顺时针旋转 90 度之后的值存入临时矩阵,然后将临时矩阵复制回原矩阵即可。
对于0 <= i, j < n的上往下第 i 个和从左往右第 j 个(均为从 0 开始计数)元素旋转后所在位置为从右往左第 i 个和从上往下第 j 个(均为从 0 开始计数),因此旋转后将位于第 j 行第 n-1-i 列。
空间复杂度O(n^2)

void rotate(int** matrix, int matrixSize, int* matrixColSize)
{
    int newmartix[matrixSize][matrixSize];
    for(int i = 0; i < matrixSize; i++)
    {
        for(int j = 0; j < matrixSize; j++)
        {
            newmartix[i][j] = matrix[i][j];
        }
    }

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

然而这道题的要求是空间复杂度为O(1)的额外空间
于是通过观察和推算可以得到
将数组沿水平翻转后 再 沿(0,0)到(n - 1, n - 1)的对角线翻转后,就可以得到目标

解法二

矩阵旋转 -> 矩阵翻转
时间复杂度O(n^2)
空间复杂度O(1)

void swap(int* a, int* b)
{
    (*b) = (*a) + (*b);
    (*a) = (*b) - (*a);
    (*b) = (*b) - (*a);
}

void rotate(int** matrix, int matrixSize, int* matrixColSize)
{
   for(int i = 0; i < matrixSize/2; i++)//水平旋转
    {
        for(int j = 0; j < matrixSize; j++)
        {
            swap(&matrix[i][j],&matrix[matrixSize - 1 -i][j]);
        }
    }

    for(int i = 0; i < matrixSize; i++)//对角线翻转
    {
        for(int j = 0; j < i; j++)
        {
            swap(&matrix[i][j],&matrix[j][i]);
        }
    }
}

这里的有个 小技巧 就是在交换的时候可以不去开辟中间变量temp,可以用数学的方法或者根据异或的交换律同样能达到目的,这样也更符合题目的要求

//或者是对a, b异或运算
void swap(int* a, int* b)
{
    (*b) = (*a) ^ (*b);
    (*a) = (*b) ^ (*a);
    (*b) = (*b) ^ (*a);
}

推论180°及270°

同理如果题目要求变为顺时针旋转180度
只需要满足先左右翻转 再 水平翻转
或者通过数学关系交换[i][j]和[matrixSize - 1 - i][matrixSize - 1 - j]
同理如果题目要求变为顺时针旋转270度 交换[i][j]和[j][N-i-1]
当然也满足顺时针旋转180再顺时针旋转90度,只需要重复解法二与上述操作即可

   //左右翻转
   for (int i = 0; i < matrixSize; i++)
    {
        for (int j = 0; j < matrixSize / 2; j++)
        {
            swap(&matrix[i][j], &matrix[i][matrixSize - j - 1]);
        }
    }
   //水平翻转
    for (int i = 0; i < matrixSize / 2; i++)
    {
        for (int j = 0; j < matrixSize; j++)
        {
            swap(&matrix[i][j], &matrix[matrixSize - 1 - i][j]);
        }
    }

    for (int i = 0, j = 0; i < matrixSize; i++) {
        for (j = 0; j < matrixSize; j++) {
            if (i == matrixSize - 1 - i && j == matrixSize - 1 - j)
                break;
            swap(&matrix[i][j], &matrix[matrixSize - 1 - i][matrixSize - 1 - j]);
        }
        if (i == matrixSize - 1 - i && j == matrixSize - 1 - j)
            break;
    }

写解题为自我回顾和分享,如有错误之处敬请指正。

你可能感兴趣的:(一个菜鸡的LeetCode日常,算法,矩阵,leetcode,算法,c语言,c++)