旋转矩阵

A. 问题介绍

今天看到一个简单的问题,以前也是遇到过的,不过今天想到了一个更好更优雅的算法,啧啧。

给一个N*N的矩阵,将它顺时针旋转90度输出。

B. 笨方法

我以前的做法有点笨,首先如下图所示,我是一层一层去做的,每一层里面分成4块,然后块和块顺时针替换,这样做的话,逻辑上麻烦,写起来也麻烦,代码量太多。
笨方法

这个笨方法的代码就不写了,有兴趣的可以自己实现一下,这次主要是想介绍一下——我刚刚yy出来的方法!!!

C. 新的方法

利用了一些几何性质,先将整个矩阵转置一下,然后以column的方向为对称轴做一下中心对称,就完成了顺时针旋转90度。逆时针旋转90度的话,只需要将第二步改成以row的方向为对称轴做中心对称即可。

由于自己画图太麻烦了,下面直接写程序来展示这两个步骤。
result

其实看图就知道为什么要做这样的两步,并且这样就能够将整个矩阵顺时针旋转90度了!
做完这个测试后,发现我的想法确实是可行的,所以,稍微封装了一下Matrix类,上效果图:
final result
图可能需要稍微介绍一下,首先是初始化了矩阵,然后顺时针旋转,结果会逐步输出,然后是逆时针旋转,很显然会变成最开始的那个矩阵,没错。然后再检查一下size是偶数的情况,也没问题,图太大就不po了。

稍微分析下复杂度,空间复杂度是O(1),不需要缓冲区嘛,原址交换,时间复杂度是O(N^2),这个目测这个问题任何有效算法都避免不了的吧?应该是lower_bound了,而且N^2的常数也很小,均摊下来是1(如果每算错的话,2333)。

D. 最后就是po代码辣~

首先头文件如下:

#ifndef __MY_MATRIX_H__
#define __MY_MATRIX_H__

#include <vector>
using namespace std;

class Matrix
{
    vector<vector<int> > m;
    int size;

public:
    Matrix(int size);
    void Transpose();
    void SpinMatrix_V();    // 竖直中心对称
    void SpinMatrix_H();    // 水平中心对称
    void display();

    void RotateCW();    // 顺时针旋转90度,CW表示clockwise
    void RotateACW();   // 顺时针旋转90度,ACW表示anticlockwise
};

#endif

Matrix.cpp代码如下:

#include "Matrix.h"
#include <assert.h>
#include <stdio.h>


Matrix::Matrix(int size)
: size(size)
{
    assert(size > 0);

    m = vector<vector<int> >(size, vector<int>(size));
    for (int row = 0; row < size; ++row)
        for (int col = 0; col < size; ++col)
            m[row][col] = row*size + col + 1;
}

void Matrix::Transpose() {
    for (int row = 0; row < size; ++row)
        for (int col = 0; col < row; ++col)
            swap(m[row][col], m[col][row]);
}

void Matrix::SpinMatrix_V() {
    for (int row = 0; row < size; ++row)
        for (int col = 0; col < size/2; ++col)
            swap(m[row][col], m[row][size-col-1]);
}

void Matrix::SpinMatrix_H() {
    for (int col = 0; col < size; ++col)
        for (int row = 0; row < size/2; ++row)
            swap(m[row][col], m[size-row-1][col]);
}

void Matrix::display() {
    printf("size=%d\n", size);
    for (int row = 0; row < size; ++row) {
        for (int col = 0; col < size; ++col)
            printf("%d\t", m[row][col]);
        printf("\n");
    }
}

void Matrix::RotateCW() {
    Transpose();
    printf("\n\n[Clockwise]After Transpose:\n");
    display();

    SpinMatrix_V();
    printf("\nFinally:\n");
    display();
}

void Matrix::RotateACW() {
    Transpose();
    printf("\n\n[Anti-clockwise]After Transpose:\n");
    display();

    SpinMatrix_H();
    printf("\nFinally:\n");
    display();
}

最后是调用Matrix类接口的main函数(十分方便):

#include "Matrix.h"
#include <stdio.h>


int main() {
    int size = 1;
    printf("Please enter the matrix size: ");
    scanf("%d", &size);

    Matrix m(size);
    printf("\nOriginal:\n");
    m.display();

    m.RotateCW();
    m.RotateACW();

    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值