矩阵NxN旋转90度 - 是否可以比O(n ^ 2)更好?

时间:2016-10-11 14:27:32

标签: c# matrix

我需要顺时针旋转矩阵90度 - 但目标是比O(n^2)更好。我发现很多例子使用2个循环,一个在另一个循环中,但那是O(n^2)

3 个答案:

答案 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指数,则可以创建旋转的矩阵。 (同样反转不会复制内容,但会修改getValuesetValue函数以访问其他字段)。

如果将基于行的矩阵转换为基于行的矩阵,然后反转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]。但那可能不是你想要的。