A. 问题介绍
今天看到一个简单的问题,以前也是遇到过的,不过今天想到了一个更好更优雅的算法,啧啧。
给一个N*N的矩阵,将它顺时针旋转90度输出。
B. 笨方法
我以前的做法有点笨,首先如下图所示,我是一层一层去做的,每一层里面分成4块,然后块和块顺时针替换,这样做的话,逻辑上麻烦,写起来也麻烦,代码量太多。
这个笨方法的代码就不写了,有兴趣的可以自己实现一下,这次主要是想介绍一下——我刚刚yy出来的方法!!!
C. 新的方法
利用了一些几何性质,先将整个矩阵转置一下,然后以column的方向为对称轴做一下中心对称,就完成了顺时针旋转90度。逆时针旋转90度的话,只需要将第二步改成以row的方向为对称轴做中心对称即可。
由于自己画图太麻烦了,下面直接写程序来展示这两个步骤。
其实看图就知道为什么要做这样的两步,并且这样就能够将整个矩阵顺时针旋转90度了!
做完这个测试后,发现我的想法确实是可行的,所以,稍微封装了一下Matrix类,上效果图:
图可能需要稍微介绍一下,首先是初始化了矩阵,然后顺时针旋转,结果会逐步输出,然后是逆时针旋转,很显然会变成最开始的那个矩阵,没错。然后再检查一下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;
}