LeetCode--数组48:旋转数组

12 篇文章 1 订阅

一、题目

给你一幅由N × N矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。

不占用额外内存空间能否做到?给你一幅由 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、对于 NxN 的矩阵,进行矩阵变换时,第N行的每一列成为新的行的第一列;第(N-1)行的每一列成为新的行的第二列;以此类推,第1行的第一列成为新的导数第二行的倒数第二列。

理解:暴力解法,建立新的矩阵
原有矩阵A,其中数值与对应索引编号如下,

123
[0,0][0,1][0,2
345
[1,0][1,1][1,2
789
[2,0][2,1][2,2

新建矩阵B,其数值与对应索引编号如下表示

[0,0][0,1][0,2
[1,0][1,1][1,2
[2,0][2,1][2,2

模拟旋转过程
i=0,j = 0 , 将数值1旋转到矩阵B的第零行第二列, [ 0, 2 ] = [ 0, 0 ]
i=0, j=1, 将数值2旋转到矩阵B的第一行第二列, [ 1, 2 ] = [ 0, 1 ]
i=0, j=2, 将数值3旋转到矩阵B的第三行第二列, [ 3, 2 ] = [ 0, 2 ]

i=1, j = 0 , 将数值4旋转到矩阵B的第零行第一列, [ 0, 1] = [ 1, 0 ]
i=1, j=1, 将数值5旋转到矩阵B的第一行第一列, [ 1, 1 ] = [ 1, 1 ]
i=1, j=2, 将数值6旋转到矩阵B的第三行第一列, [ 2, 1 ] = [ 1, 2 ]

i=2, j = 0 , 将数值7旋转到矩阵B的第零行第零列, [ 0, 0 ] = [ 2, 0 ]
i=2, j=1, 将数值8旋转到矩阵B的第一行第零列, [ 1, 0 ] = [ 2, 1 ]
i=2, j=2, 将数值9旋转到矩阵B的第三行第零列, [ 2, 0 ] = [ 2, 2 ]

在上述过程中,新矩阵中的行数与j 相关,列数与i (n-1-i) 相关。也就是说,

// 伪代码
/*
for(i=0;  i<n;  j++ ){
	for(j=0;  j<n; j++){
	B [j] [n-1-i] = A[i][j];
}
}
*/

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();  // 矩阵matrix 的长度

        auto matrixB = matrix;  // vecotr  新建一个矩阵matrixB  大小维度与matrix 相同
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                matrixB[j][n-1-i] = matrix[i][j];  // 依次遍历交换不同索引处的数值
            }
        }

        matrix = matrixB;  // 将新的矩阵赋值给原矩阵matrix
    }
};

原地解法

引入一个临时变量, temp.
在暴力解法中,我们已经知道一个关键变换关系,B[col][n-1-row] = A[row][col];

那么如果是同一个矩阵的话,写为A[col][n-1-row] = A[row][col]; 那么原来的值就会被覆盖掉。用Temp,存储这个新的数值,temp = A[col][n-1-row] 避免被覆盖掉;

那么就存在一个关键关系,在遍历的过程中
{ t e m p = A [ c o l ] [ n − 1 − r o w ] A [ c o l ] [ n − 1 − r o w ] = A [ r o w ] [ c o l ] \left\{ \begin{aligned} temp = A[col][n-1-row] \\ A[col][n-1-row] = A[row][col]\\ \end{aligned} \right. {temp=A[col][n1row]A[col][n1row]=A[row][col]

还是按照关键关系B[col][n-1-row] = A[row][col], 经过上述遍历过程之后,A[col][n-1-row]下一步应该变换为A[n-1-row][n-1-col]. 那么进一步的遍历关系可以写为

{ t e m p = A [ c o l ] [ n − 1 − r o w ] A [ c o l ] [ n − 1 − r o w ] = A [ r o w ] [ c o l ] A [ n − 1 − r o w ] [ n − 1 − c o l ] = A [ c o l ] [ n − 1 − r o w ] \left\{ \begin{aligned} temp = A[col][n-1-row] \\ A[col][n-1-row] = A[row][col]\\ A[n-1-row][n-1-col] = A[col][n-1-row] \\ \end{aligned} \right. temp=A[col][n1row]A[col][n1row]=A[row][col]A[n1row][n1col]=A[col][n1row]

进一步的,当前变换为A[n-1-row][n-1-col],按照关键变换关系B[col][n-1-row] = A[row][col], A[n-1-row][n-1-col]下一步应该变换为
A[n-1-row][n-1-col]=A[n-1-col][n-1-(n-1-row)]=A[n-1-col][row]. 进一步的遍历关系可以写为
{ t e m p = A [ c o l ] [ n − 1 − r o w ] A [ c o l ] [ n − 1 − r o w ] = A [ r o w ] [ c o l ] A [ n − 1 − r o w ] [ n − 1 − c o l ] = A [ c o l ] [ n − 1 − r o w ] A [ n − 1 − c o l ] [ r o w ] = A [ n − 1 − r o w ] [ n − 1 − c o l ] \left\{ \begin{aligned} temp = A[col][n-1-row] \\ A[col][n-1-row] = A[row][col]\\ A[n-1-row][n-1-col] = A[col][n-1-row] \\ A[n-1-col][row]=A[n-1-row][n-1-col] \\ \end{aligned} \right. temp=A[col][n1row]A[col][n1row]=A[row][col]A[n1row][n1col]=A[col][n1row]A[n1col][row]=A[n1row][n1col]

将当前旋转的结果A[n-1-col][row],按照关键变换关系B[col][n-1-row] = A[row][col], A[n-1-col][row]下一步变换为A[n-1-col][row] = A[n-1-(n-1-col)][row] = A[col][row]. 那么,遍历关系进一步的可以写为
{ t e m p = A [ c o l ] [ n − 1 − r o w ] A [ c o l ] [ n − 1 − r o w ] = A [ r o w ] [ c o l ] A [ n − 1 − r o w ] [ n − 1 − c o l ] = A [ c o l ] [ n − 1 − r o w ] A [ n − 1 − c o l ] [ r o w ] = A [ n − 1 − r o w ] [ n − 1 − c o l ] A [ c o l ] [ r o w ] = A [ n − 1 − c o l ] [ r o w ] \left\{ \begin{aligned} temp = A[col][n-1-row] \\ A[col][n-1-row] = A[row][col]\\ A[n-1-row][n-1-col] = A[col][n-1-row] \\ A[n-1-col][row]=A[n-1-row][n-1-col] \\ A[col][row] = A[n-1-col][row]\\ \end{aligned} \right. temp=A[col][n1row]A[col][n1row]=A[row][col]A[n1row][n1col]=A[col][n1row]A[n1col][row]=A[n1row][n1col]A[col][row]=A[n1col][row]
依次类推,目的是最终实现
{ t e m p = A [ r o w ] [ c o l ] A [ r o w ] [ c o l ] = t e m p \left\{ \begin{aligned} temp = A[row][col]\\ A[row][col] = temp\\ \end{aligned} \right. {temp=A[row][col]A[row][col]=temp
相互交换。

上述讲述的是原地交换的原理,那么如何实现位置交换?
(暂时还没有明白其中的思想,等待某一天的悟性!!!)

  • 当 nn 为偶数时,我们需要枚举 n 2 / 4 = ( n / 2 ) × ( n / 2 ) n 2 / 4 = ( n / 2 ) × ( n / 2 ) n^2 / 4 = (n/2) \times (n/2)n 2 /4=(n/2)×(n/2) n2/4=(n/2)×(n/2)n2/4=(n/2)×(n/2)个位置(针对4X4 的矩阵而言)
  • 当 nn 为奇数时,由于中心的位置经过旋转后位置不变,我们需要枚举 ( n 2 − 1 ) / 4 = ( ( n − 1 ) / 2 ) × ( ( n + 1 ) / 2 ) ( n 2 − 1 ) / 4 = ( ( n − 1 ) / 2 ) × ( ( n + 1 ) / 2 ) (n^2-1) / 4 = ((n-1)/2) \times ((n+1)/2)(n 2 −1)/4=((n−1)/2)×((n+1)/2) (n21)/4=((n1)/2)×((n+1)/2)(n21)/4=((n1)/2)×((n+1)/2)个位置
//  放上官方给出的答案!!
// 小菜目前还未完成这个代码的理解!!!
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        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 - 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;
            }
        }
    }
};

三、补充知识

四、他山之石

1、官方解答.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shae Zhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值