原地矩阵旋转

发布于 2024-11-05 12:01:55 字数 2004 浏览 0 评论 0原文

我发现一个有趣的问题,要求将 NxN 矩阵原地旋转 90 度。我的 C 语言递归解决方案如下。然而,当我查找其他解决方案时,大多数解决方案都使用嵌套的 for 循环来完成任务(这似乎工作正常)。嵌套循环实现似乎在 O(n^2) 时间内运行。

看: 如何旋转二维数组?

我相信递归解决方案的运行时间为 O( (n^2-n)/2 ),也就是 O(n^2)。我的问题有两个方面。 1)我上面的复杂性分析对于递归和非递归解决方案都正确吗?2)是否有一些我还没有找到的高效或巧妙的方法来旋转矩阵?

TIA。

#include <stdio.h>
#include <stdlib.h>


int SIZE = 0;


/**
 * In-place, recursive, clockwise, 90 degree matrix rotation.
 */
static void rotate_in_place( int matrix[][SIZE], int n )
{
    if( n < 2 )
        return;


    int temp1, temp2;

    for( int i = 0; i < (n-1); i++ )
    {
        temp1 = matrix[i][n-1];
        matrix[i][n-1] = matrix[0][i];

        temp2 = matrix[n-1][n-i-1];
        matrix[n-1][n-i-1] = temp1;

        temp1 = matrix[n-i-1][0];
        matrix[n-i-1][0] = temp2;

        matrix[0][i] = temp1;
    }


    matrix = ((int*)matrix) + SIZE + 1;
    n -= 2;
    rotate_in_place( matrix, n );
}


static void print_matrix( int matrix[][SIZE] )
{
    printf( "\n" );
    for( int i = 0; i < SIZE; i++ )
    {
        for( int j = 0; j < SIZE; j++ )
            printf( "%4i ", matrix[i][j] );

        printf( "\n" );
    }
}


int main()
{

    // Create some matrices and rotate them.
    //
        int matrices = 10;

        for( int i = 2; i < matrices; i++ )
        {
            int matrix[i][i];

            int count = 0;
            for( int j = 0; j < i; j++ )
                for( int k = 0; k < i; k++ )
                    matrix[j][k] = ++count;


            printf( "\n\nRotating %ix%i matrix.\n", i, i );

            SIZE = i;

            printf( "\nOriginal matrix.\n" );
            print_matrix( matrix );

            rotate_in_place( matrix, i );

            printf( "\n\nRotated matrix.\n" );
            print_matrix( matrix );
        }


    return EXIT_SUCCESS;
}

An interesting question I found, asked that an NxN matrix be rotated, in-place by 90 degrees. My recursive solution, in C, is below. However when I looked up other solutions, most used a nested for loop to accomplish the task (which seems to work fine). The nested loop implementations appear to run in O(n^2) time.

See:
How do you rotate a two dimensional array?

I believe the recursive solution runs in O( (n^2-n)/2 ), which is O(n^2) as well. My question is two-fold. 1) Is my complexity analysis above correct for both the recursive and non-recursive solutions, and 2) Is there some highly efficient or clever way to rotate a matrix that I haven't found?

TIA.

#include <stdio.h>
#include <stdlib.h>


int SIZE = 0;


/**
 * In-place, recursive, clockwise, 90 degree matrix rotation.
 */
static void rotate_in_place( int matrix[][SIZE], int n )
{
    if( n < 2 )
        return;


    int temp1, temp2;

    for( int i = 0; i < (n-1); i++ )
    {
        temp1 = matrix[i][n-1];
        matrix[i][n-1] = matrix[0][i];

        temp2 = matrix[n-1][n-i-1];
        matrix[n-1][n-i-1] = temp1;

        temp1 = matrix[n-i-1][0];
        matrix[n-i-1][0] = temp2;

        matrix[0][i] = temp1;
    }


    matrix = ((int*)matrix) + SIZE + 1;
    n -= 2;
    rotate_in_place( matrix, n );
}


static void print_matrix( int matrix[][SIZE] )
{
    printf( "\n" );
    for( int i = 0; i < SIZE; i++ )
    {
        for( int j = 0; j < SIZE; j++ )
            printf( "%4i ", matrix[i][j] );

        printf( "\n" );
    }
}


int main()
{

    // Create some matrices and rotate them.
    //
        int matrices = 10;

        for( int i = 2; i < matrices; i++ )
        {
            int matrix[i][i];

            int count = 0;
            for( int j = 0; j < i; j++ )
                for( int k = 0; k < i; k++ )
                    matrix[j][k] = ++count;


            printf( "\n\nRotating %ix%i matrix.\n", i, i );

            SIZE = i;

            printf( "\nOriginal matrix.\n" );
            print_matrix( matrix );

            rotate_in_place( matrix, i );

            printf( "\n\nRotated matrix.\n" );
            print_matrix( matrix );
        }


    return EXIT_SUCCESS;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

白芷 2024-11-12 12:01:56

就地C解决方案如下

void rotateRight(int matrix[][SIZE], int length) {

    int layer = 0;

    for (int layer = 0; layer < length / 2; ++layer) {

        int first = layer;
        int last = length - 1 - layer;

        for (int i = first; i < last; ++i) {

            int topline = matrix[first][i];
            int rightcol = matrix[i][last];
            int bottomline = matrix[last][length - layer - 1 - i];
            int leftcol = matrix[length - layer - 1 - i][first];

            matrix[first][i] = leftcol;
            matrix[i][last] = topline;
            matrix[last][length - layer - 1 - i] = rightcol;
            matrix[length - layer - 1 - i][first] = bottomline;
        }
    }
}

in place C solution follows

void rotateRight(int matrix[][SIZE], int length) {

    int layer = 0;

    for (int layer = 0; layer < length / 2; ++layer) {

        int first = layer;
        int last = length - 1 - layer;

        for (int i = first; i < last; ++i) {

            int topline = matrix[first][i];
            int rightcol = matrix[i][last];
            int bottomline = matrix[last][length - layer - 1 - i];
            int leftcol = matrix[length - layer - 1 - i][first];

            matrix[first][i] = leftcol;
            matrix[i][last] = topline;
            matrix[last][length - layer - 1 - i] = rightcol;
            matrix[length - layer - 1 - i][first] = bottomline;
        }
    }
}
萌吟 2024-11-12 12:01:56

旋转不能在少于 n^2 次操作中完成,因为您需要交换所有元素。然而,通常情况下,由于旋转会非常严重地破坏缓存,因此我们会避免执行它;)

Rotation can't be done in less than n^2 operations as you are required to swap all element. Usually, however, as rotation trash the cache pretty hard, we avoid performing it ;)

你另情深 2024-11-12 12:01:56

您的复杂性分析是正确的,但也非常令人困惑。由于矩阵中的元素数量为 n²,因此 O(n²) 实际上是输入大小的线性时间,这才是重要的数字。

如果您想在旋转后打印整个矩阵,那么线性时间是最好的选择。对于其他操作,明智的做法是不要就地旋转矩阵,而是编写一个 适配器 更改其索引,因此可以访问旋转矩阵的元素,而无需在内存中进行实际旋转。

Your complexity analysis is correct, but also very confusing. Since the number of elements in the matrix is n², O(n²) is effectively linear time in the size of the input, which is the figure that matters.

If you want to print the entire matrix after rotating it, then linear time is the best you can do. For other operations, it would be wiser not to rotate the matrix in-place but instead write an adapter that changes its indexing, so elements of the rotated matrix can be accessed without doing the actual rotation in memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文