【问题标题】:Rotate inner-square in 2D Array在二维数组中旋转内部正方形
【发布时间】:2018-02-04 01:50:08
【问题描述】:

我想旋转二维数组中的内部正方形,如下面的“示例”图像:

给定左上角和右下角的位置。

我尝试将它拆分为另一个二维数组,然后旋转它。但它会消耗大量的 O 循环运行时间和内存。

static int[][] rotateMatrix(int[][] subSquare) {
    int n = subSquare.length;
    int[][] temp = new int [n][n];
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            temp[i][j] = subSquare[n - j - 1][i];
        }
    }
    return temp;
}

static int[][] getInnerSquare(int[][] square, int ai, int bi, int di){
    int g = 0, h = 0;
    int[][] innerSquare = new int[di+1][di+1];
    for(int k = ai - 1; k < ai + di; k++) {
        for(int j = bi - 1; j < bi + di; j++) {
            innerSquare[g][h] = square[k][j];
            h++;
        }
        g++;
        h=0;
    }
    return innerSquare;
}
    static void replaceInnerSquare(int[][] square, int[][] innerSquare, int ai, int bi, int di) {
    int g = 0, h = 0;
    for(int i = ai - 1; i < ai + di; i++) {
        for(int j = bi - 1; j < bi + di; j++) {
            square[i][j] = innerSquare[g][h];
            h++;
        }
        g++;
        h=0;
    }
}

public static void main(String[] args){
    //follow the image: ai = 1, bi = 2, di = 3 
    // top-left corner (ai, bi), bottom-right corner(ai + di, bi + di)
    subSquare = getInnerSquare(square, ai, bi, di);         
    subSquare = rotateMatrix(subSquare);
    replaceInnerSquare(square, subSquare, ai, bi, di);
}

这个问题有没有更好的解决方案? 谢谢!!!!

【问题讨论】:

  • 好的,请显示您拥有的当前代码以及您为实现所需输出所做的尝试。 “但是它需要大量的 O 循环运行时间和内存”完全没有意义,在您声称的 O(n) 情况下,n 是多少?
  • 更新了我的代码
  • 您当然不必将正方形复制到另一个矩阵中。观察比四次旋转后任何元素返回到其原始位置。所以只有四个元素受到影响。编写一个重新排列这四个元素的方法并在循环中调用它。
  • 要考虑的更好/更差解决方案的定量衡量标准是什么 - 您将如何决定最佳答案? 总 SLOC 计数? 矩阵以纳秒为单位的旋转部分持续时间?最后将比较矩阵的参考大小吗?感谢澄清指标。

标签: java algorithm performance matrix multidimensional-array


【解决方案1】:

Daniel 的解决方案将每个元素移动两次。 在这个解决方案中,每个元素只移动一次:

x,y:正方形的左上角

N:正方形的大小

void rotate(int x, int y, int N) {
    for (int i = 0; i < (N + 1) / 2; i++) {
        for (int j = 0; j < N / 2; j++) {
            int temp = M[x + i][y + j];
            M[x + i][y + j] = M[x + N - 1 - j][y + i];
            M[x + N - 1 - j][y + i] = M[x + N - 1 - i][y + N - 1 - j];
            M[x + N - 1 - i][y + N - 1 - j] = M[x + j][y + N - 1 - i];
            M[x + j][y + N - 1 - i] = temp;
        }
    }
}

【讨论】:

    【解决方案2】:

    关键是要观察,如果你想把这个子矩阵旋转 90º,你必须把它转置,然后把每一行都还原。

    #include <bits/stdc++.h>
    using namespace std;
    
    int M[7][7] = {
        {0,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}
    };
    
    void print(){
        for(int i = 0; i < 7; i++){
            for(int j = 0; j < 7; j++){
                cout<< (M[i][j] < 10? " " : "") << M[i][j]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
    
    void transpose(int x0, int y0, int x1, int y1){
        int offset = 1;
        int len = x1 - x0 + 1;
        for(int i = 0; i < len; i++){
            for(int j = offset; j < len; j++){
                int t1 = j - x0, t2 = i - y0;
                swap(M[x0 + i][y0 + j],M[y0 + j - 1][x0 + i + 1]);
            }
            offset++;
        }
    }
    
    void invertLines(int x0, int y0, int x1, int y1){
        int len = x1 - x0 + 1;
        for(int i = 0; i < len; i++)
            for(int j = 0, sz = len/2; j < sz; j++)
                swap(M[x0 + i][y0 + j], M[x0 + i][y0 + len - j - 1]);
    }
    
    void rotate90(int x0, int y0, int x1, int y1){
        transpose(x0, y0, x1, y1);
        print();
        invertLines(x0, y0, x1, y1);
        print();
    }
    
    
    
    int main(){
        print();
        rotate90(1,2,4,5);
    }
    

    这应该可以完成工作

    【讨论】:

    • 上面的样本正方形,x0 = 1, y0 = 2 然后 i = 1, j = 3 M[i][j] = 10, M[j][i] = 22(不在内部正方形)。转置不正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 2021-11-02
    • 1970-01-01
    • 2021-08-21
    • 2019-03-06
    • 1970-01-01
    相关资源
    最近更新 更多