人人都來寫算法 之 矩陣順時針旋轉90度,空間效率O(1),時間效率O(n*n)

給你一個矩形圖片,假設每位像素是用整形標識,將圖片位圖順時針旋轉90度。空間複雜度O(1), 時間複雜度O(n*n)


兩種方案可以選擇:
1. 利用圖片矩形的特性,將其剝洋蔥一樣,一層一層處理,每一層逐個將四條邊順時針交換;
2. 先將圖片上下翻轉矩陣,所有元素再在沿着主對角線交換位置即可。(當然,也可以先沿着主對角線交換,再左右翻轉矩陣)
針對上面的兩個方案,各提供了兩個略有差別的函數實現,共大家參考:

#include <iostream>
#include <iomanip>

using std::cout;
using std::endl;
using std::setw;

const int SIZE = 4;
const int SIZE_1 = 7;

void printImage(int image[][SIZE])
{
    for(int i=0; i<SIZE; ++i)
    {
        for(int j=0; j<SIZE; ++j)
        {
            cout<<setw(4)<<image[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<"-----------------------------"<<endl;
}

void printImage_1(int image[][SIZE_1])
{
    for(int i=0; i<SIZE_1; ++i)
    {
        for(int j=0; j<SIZE_1; ++j)
        {
            cout<<setw(4)<<image[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<"-----------------------------"<<endl;
}

void swap(int &a, int &b)
{
    if(&a == &b)
    {
        return;
    }
    int temp = a;
    a = b;
    b = temp;
}

void transpose90_zero(int matrix[][SIZE])
{
    //Diagonal Flip
    for(int i=0; i<SIZE; ++i)
    {
        for(int j=i+1; j< SIZE; ++j)
        {
            swap(matrix[i][j], matrix[j][i]);
        }
    }

    //Flip form left to right
    for(int i=0; i<SIZE; ++i)
    {
        for(int j=0; j<SIZE/2; j++)
        {
            swap(matrix[i][j], matrix[i][SIZE-j-1]);
        }
    } 
}

void transpose90_one(int matrix[][SIZE])
{
    //Flip up and down
    for(int i=0; i<SIZE/2; ++i)
    {
        for(int j=0; j<SIZE; j++)
        {
            swap(matrix[i][j], matrix[SIZE-i-1][j]);
        }
    }
    
    //Diagonal Flip
    for(int i=0; i<SIZE; ++i)
    {
        for(int j=i+1; j< SIZE; ++j)
        {
            swap(matrix[i][j], matrix[j][i]);
        }
    }
}

void transpose90_two(int matrix[SIZE][SIZE])
{
    for(int layer=0; layer<SIZE/2; ++layer)
    {
        int first = layer;
        int last = SIZE-1-layer;

        for(int i=first; i<last; ++i)
        {
            int offset = i - first;
            int top = matrix[first][i];
            matrix[first][i] = matrix[last-offset][first];
            matrix[last-offset][first] = matrix[last][last-offset];
            matrix[last][last-offset] = matrix[i][last];
            matrix[i][last] = top;
        }
    }
}

void transpose90_three(int matrix[SIZE][SIZE])
{
    for(int layer=0; layer<SIZE/2; ++layer)
    {
        int last = SIZE-layer -1;
        int iter = 0;
        for(int i=layer; i<last; ++i)
        {
            int reverse_i = last - iter;
            int top = matrix[layer][i];
            matrix[layer][i] = matrix[reverse_i][layer];
            matrix[reverse_i][layer] = matrix[last][reverse_i];
            matrix[last][reverse_i] = matrix[i][last];
            matrix[i][last] = top;
            iter++;
        }
    }
}

void transpose90_zero_1(int matrix[][SIZE_1])
{
    //Diagonal Flip
    for(int i=0; i<SIZE_1; ++i)
    {
        for(int j=i+1; j< SIZE_1; ++j)
        {
            swap(matrix[i][j], matrix[j][i]);
        }
    }

    //Flip form left to right
    for(int i=0; i<SIZE_1; ++i)
    {
        for(int j=0; j<SIZE_1/2; j++)
        {
            swap(matrix[i][j], matrix[i][SIZE_1-j-1]);
        }
    } 
}

void transpose90_one_1(int matrix[][SIZE_1])
{
    //Flip up and down
    for(int i=0; i<SIZE_1/2; ++i)
    {
        for(int j=0; j<SIZE_1; j++)
        {
            swap(matrix[i][j], matrix[SIZE_1-i-1][j]);
        }
    }
    
    //Diagonal Flip
    for(int i=0; i<SIZE_1; ++i)
    {
        for(int j=i+1; j< SIZE_1; ++j)
        {
            swap(matrix[i][j], matrix[j][i]);
        }
    }
}

void transpose90_two_1(int matrix[][SIZE_1])
{
    for(int layer=0; layer<SIZE_1/2; ++layer)
    {
        int first = layer;
        int last = SIZE_1-1-layer;

        for(int i=first; i<last; ++i)
        {
            int offset = i - first;
            int top = matrix[first][i];
            matrix[first][i] = matrix[last-offset][first];
            matrix[last-offset][first] = matrix[last][last-offset];
            matrix[last][last-offset] = matrix[i][last];
            matrix[i][last] = top;
        }
    }
}

void transpose90_three_1(int matrix[][SIZE_1])
{
    for(int layer=0; layer<SIZE_1/2; ++layer)
    {
        int last = SIZE_1-layer -1;
        int iter = 0;
        for(int i=layer; i<last; ++i)
        {
            int reverse_i = last - iter;
            int top = matrix[layer][i];
            matrix[layer][i] = matrix[reverse_i][layer];
            matrix[reverse_i][layer] = matrix[last][reverse_i];
            matrix[last][reverse_i] = matrix[i][last];
            matrix[i][last] = top;
            iter++;
        }
    }
}

int main()
{
    //Test even matrix
    int image[SIZE][SIZE] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}};
    printImage(image);
    transpose90_zero(image);
    printImage(image);
    transpose90_one(image);
    printImage(image);
    transpose90_two(image);
    printImage(image);
    transpose90_three(image);
    printImage(image);
    
    //Test odd matrix
    int image_1[SIZE_1][SIZE_1] = {
        {1,2,3,4,5,6,7}, 
        {8,9,10,11,12,13,14}, 
        {15,16,17,18,19,20,21}, 
        {22,23,24,25,26,27,28},
        {29,30,31,32,33,34,35},
        {36,37,38,39,40,41,42},
        {43,44,45,46,47,48,49}};
    printImage_1(image_1);
    transpose90_zero_1(image_1);
    printImage_1(image_1);
    transpose90_one_1(image_1);
    printImage_1(image_1);
    transpose90_two_1(image_1);
    printImage_1(image_1);
    transpose90_three_1(image_1);
    printImage_1(image_1);
    
    getchar();
}

代碼第一眼就看起來不舒服,因爲重複代碼比較明顯,如果消除這個重複只能使用指針操作二維數組。
重構的代碼見另一篇文章:

發佈了96 篇原創文章 · 獲贊 26 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章