我需要顺时针旋转矩阵90度 - 但目标是比O(n^2)
更好。我发现很多例子使用2个循环,一个在另一个循环中,但那是O(n^2)
。
答案 0 :(得分:1)
好吧,如果您可以自由控制Matrix的表示形式,我可以在O(1)中给你一个:)。
假设您的矩阵位于满足IMatrix接口
的对象中interface IMatrix
{
double getValue(int index_x, int index_y);
void setValue(int index_x, int index_y, double value);
}
您可以通过不同方式实现它,例如:
class RowBasedMatrix implements IMatrix
{
//an array of rows
double[][] values;
//size of the Matrix
int N;
//this is explained later
bool invert_x, invert_y;
RowBasedMatrix(double[][] values, int N, bool invert_x, bool invert_y)
{
this.values = values;
this.N = N;
this.invert_x = invert_x;
this.invert_y = invert_y;
}
double getValue(int index_x, int index_y)
{
if(invert_x)
index_x = N - 1 - index_x
if(invert_y)
index_y = N - 1 - index_y
return values[index_y][index_x];
}
double setValue(int index_x, int index_y, double value)
{
if(invert_x)
index_x = N - 1 - index_x
if(invert_y)
index_y = N - 1 - index_y
values[index_y][index_x] = value;
}
}
class ColumnBasedMatrix implements IMatrix
{
//an array of columns
double[][] values;
//size of the Matrix
int N;
//this is explained later
bool invert_x, invert_y;
RowBasedMatrix(double[][] values, int N, bool invert_x, bool invert_y)
{
this.values = values;
this.N = N;
this.invert_x = invert_x;
this.invert_y = invert_y;
}
double getValue(int index_x, int index_y)
{
if(invert_x)
index_x = N - 1 - index_x
if(invert_y)
index_y = N - 1 - index_y
return values[index_x][index_y];
}
double setValue(int index_x, int index_y, double value)
{
if(invert_x)
index_x = N - 1 - index_x
if(invert_y)
index_y = N - 1 - index_y
values[index_x][index_y] = value;
}
}
这个想法是:您可以将values
数组中的RowBasedMatrix
数组重用到values
的{{1}}中,该ColumnBasedMatrix
现在实际上是一个具有镜像值基础的矩阵从(1,1)到(N,N)的对角线。
如果反转x或y指数,则可以创建旋转的矩阵。 (同样反转不会复制内容,但会修改getValue
和setValue
函数以访问其他字段)。
如果将基于行的矩阵转换为基于行的矩阵,然后反转x坐标,则实际上有90°顺时针旋转矩阵。
编辑:扩展示例代码
编辑2:使用Matrix类的示例代码。
double[][] raw matrix_data =
new double[][] { {0.0, 0.1, 0.2, 0.3, 0.4}
{1.0, 1.1, 1.2, 1.3, 1.4}
{2.0, 2.1, 2.2, 2.3, 2.4}
{3.0, 3.1, 3.2, 3.3, 3.4}
{4.0, 4.1, 4.2, 4.3, 4.4} };
int main(...)
{
//this Matrix returns the values as visible above
IMatrix default = new RowBasedMatrix(matrix_data, 5, false, false)
double test = default.getValue(0, 4);
//test is set to 4.0
test = default.getValue(3, 1);
//test is set to 1.3
//this Matrix return values as if it had this value set:
// /0.4, 0.3, 0.2, 0.1, 0.0\
// | 1.4, 1.3, 1.2, 1.1, 1.0 |
// | 2.4, 2.3, 2.2, 2.1, 2.0 |
// | 3.4, 3.3, 3.2, 3.1, 3.0 |
// \4.4, 4.3, 4.2, 4.1, 4.0/
IMatrix xInverted = new RowBasedMatrix(matrix_data, 5, true, false);
test = xInverted.getValue(0, 4);
//test is set to 4.4
test = xInverted.getValue(3, 1);
//test is set to 1.1
//now, if we use the column-matrix (switch x- and y-coordinates):
// /0.0, 1.0, 2.0, 3.0, 4.0\
// | 0.1, 1.1, 2.1, 3.1, 4.1 |
// | 0.2, 1.2, 2.2, 3.2, 4.2 |
// | 0.3, 1.3, 2.3, 3.3, 4.3 |
// \0.4, 1.4, 2.4, 3.4, 4.4/
IMatrix columns = new ColumnBasedMatrix(matrix_data, 5, false, false);
test = columns.getValue(0, 4);
//test is set to 0.4
test = columns.getValue(3, 1);
//test is set to 3.1
//if we invert this matrix's x-coordinates again, we get a 90° clockwise rotated value set
IMatrix rotated = new ColumnBasedMatrix(matrix_data, 5, true, false);
}
此实现不会复制任何值(这将花费O(n ^ 2))。 相反,每次访问值时都会进行小的O(1)计算。
(请注意,我的实现并不完美,例如,对非方形矩阵不起作用)
答案 1 :(得分:0)
由于矩阵具有n^2
条目,O(n^2)
的运行时复杂性是最佳的,因为它恰好是输入和输出的长度。话虽如此,取决于应用程序,可能根本不需要旋转矩阵,而只是通过在元素方式访问时旋转索引来操纵对矩阵的访问。
答案 2 :(得分:0)
如果您想使事情复杂化,您可以定义Rotated90Matrix : Matrix
,其中Rotated90Matrix[i][j]
返回正确的Matrix[a][b]
。但那可能不是你想要的。