矩阵变换

矩阵

zigzag打印矩阵

假设A、B点指向(0,0)

定义如下变量

  • int Ar = 0 A的行号

  • int Ac = 0 A的列号

  • int Br = 0 B行号

  • int Bc = 0 B的列号

  • int endr = matrix.length - 1 最后一行

  • int endc = mrtrix[0].length - 1最后一列

  • boolean fromUp = false 是否自右下向左上打印

  • A先往右走,走到不能往右走了,再往下走

    Ar = Ac == endC ? Ar : Ar+1;//是否走到第一行最右边了(一行最右一列了)?不是就往右走
    Ac = Ac == endc ? Ac+1 : Ac;//是否走到最右边一列了?是就往下走
  • B和A同步,先往下走,走到不能往下走了,再往右走

    Bc = Bc == endR ? Bc : Bc+1;//是否走到最下面一行了?不是就继续向下走
    Br = Br == endR ? Br+1 : Br;//是否走到最下面一列了?是就往右走

把打印交给一个方法printLevel(Boolean),调度问题由AB实现

  • 第一次打印AB两点连线先右下向左上打印 boolean fromUp = false

  • 第二次打印AB连线自左上向右下打印 每次打印都切换fromUp为相反 fromUp = !fromUp

public void printZigzagMatrix(int[][] martrix){
    int Ar = 0;
    int Ac = 0;
    int Br = 0;
    int Bc = 0;
    int endr = martix.length - 1;
    int endc = martix[0].length - 1;
    boolean fromUp = false;
    while(Ac != endc + 1){//当A的列不会往下移动到越界 Br !=endr + 1
        printLevel(martrix, Ac, Ar, Bc, Br, fromUp);
        Ar = Ac == endc ? Ar+1 : Ar;
        Ac = Ac == endc ? Ac : Ac+1;
        Bc = Br == endr ? Bc+1 : Bc;
        Br = Br == endr ? Br : Br+1;
        fromUp = !fromUp;
    }
}
public void printLevel(int[][] martrix, int tr, int tc, int dR, int dC, boolean fromUp){
    if(fromUp){
        //当没有超过当前第列
        while(tR != dR + 1){
            sout(martrix[tC++][tR--]+" ");   
        }
    }else{
        while(dR != tR - 1){
            sout(martrix[dR--][dC++]+" ");
        }
    }
}

转圈打印 / leetcode 54. 螺旋矩阵

假设这个圈的左上角点[a][b]右上角[a][d]右下角[c][d]左下角[c][b]

从左上角往右上角打印,注意b不能碰到d

再从右上角往右下角打印,注意a不能碰到c

再从右下角往左下角打印,注意d不能碰到b

最后再从左下角往左上角打印,注意c不能碰到a

打印完一圈后左上角点向右下方移动一个a++ ,b++,右下角点向左上方移动一个c-- ,d--

如果a==c的时候说明只剩一条横线了,如果b==d的时候说明只剩一条竖线了

 

public void print(int[][] martrix){
    int a = 0;
    int b = 0;
    int c = martrix.length - 1;
    int d = martrix[0].length - 1;
    while(a <= c && b <= d){ //边界条件就是这四个角,必须保持a在c上方,b在d上方
        printMartrix(martrix[], a++, b++, c--, d--);//每次打印左上角往右下移动,右下角往左上上移动
    }
}
public void printMartrix(int[][] martrix, int a, int b, int c, int d){
    if(a == c){//如果`a==c`的时候说明只剩一条横线了
        for(int i = b; i < d ; i++)
            sout(martrix[a][i]+" ");
    }else if(b == d){//如果`b==d`的时候说明只剩一条竖线了
        for(int i = a ; i< c; i++)
            sout(martrix[i][b]+" ");
    }else{
        int i = a;
        int j = b;
        //从左上角往右上角打印,注意b不能碰到d
        while(j < d){
            sout(martix[i][j++]+" ");
        }
        //再从右上角往右下角打印,注意a不能碰到c
        while(i < c){
            sout(martrix[i++][j]+" ")
        }
        //再从右下角往左下角打印,注意d不能碰到b
        while(j > b){
            sout(martrix[i][j--]+" ")
        }
        //再从右下角往左下角打印,注意d不能碰到b
        while(i > a){
            sout(martix[i--][j]+" ")
        }
    }
    
}
public void printMatrix(int[][] matrix){
    if(matrix == null|| matrix.length == 0 || matrix[0].length == 0){
        return;
    }
    int a = 0;
    int b = 0;
    int c = matrix.length-1;
    int d = matrix[0].length-1;
    int numEle = matrix.length * matrix[0].length;//矩阵中元素的数量
    //判断矩阵内元素的个数,如果小于1就说明遍历完了,弹出
    while(numEle >= 1){
        for(int i = b; i <= d && numEle >= 1 ;i++){
            sout(matrix[a][i]+" ");
            //每次把一个元素添加到list中,就减少一下整个矩阵的元素个数
            numEle --;
        }
        a++;//a变为a的下一个就相当于,最左上的点往下移动一位
        for(int i = a ; i <= c && numEle >= 1 ;i++){//a在上面已经变了,这就是从右上角的右边一个元素开始加入list
            sout(matrix[i][d]+" ");
            numEle --;
        }
        d--;//d变为上一个,就相当于右下的点往里移动一位
        for(int i = d ; i <= b &&numEle >= 1;i++){//d在上面已经变了,这就是从右下角的左边一个元素开始加入list
            sout(matrix[c][i]+" ");
            numEle --;
        }
        c++;//c变为上一个,就相当于右下的点向上移动了一位
        for(int i = c ; i <= a &&numEle >= 1 ;i++){{//c在上面已经变了,这里是从左下角上面一个元素开始加入list中,并且a也变了,就是截至到左上角的下一个元素停止加入
            sout(matrix[b][i]+" ");
            numEle --;
        }
        b--;//b变为下一个,左上的点向里移动了一位
    }
}

正方形矩阵直角旋转

和上一道题类似,我们可以得到上下左右四个角的位置

假设这个圈的左上角点[a][b]右上角[a][d]右下角[c][d]左下角[c][b]

分组操作

小组1:四个角 —— 左上去右上的位置、右上去右下的位置、右下去左下的位置、左下去左上的位置

小组2:四个角各顺时针往后的位置 ——

小组3:.....

当4*4的矩阵,有3个小组,5X5的有4个小组,得到nXn的有n-1小组,可以认为d-b个小组,小组内每个元素下标为(0~d-b)

由循环得到小组内每个元素的下标

for(int i = 0; i < d-b; i++){
    //小组第一个下标
    martrix[a][b+i];
    //小组第二个下标
    martrix[a+i][d];
    //小组第三个下标
    martrix[c][d-i];
    //小组第四个下标
    martrix[c-i][b];
}

进一步我们可以知道如何交换

public void swapMartrix(int[][] martrix, int a, int b, int c, int d){
    int temp = 0;
        for(int i = 0; i < d-b ;i++){
        //记录第一个点的值
        temp = martrix[a][b+i];
        //第一个点变为第四个点
        martrix[a][b+i] = martrix[c-i][b]
        //第四个点,变为第三个点
        martrix[c-i][b] = martrix[c][d-i];
        //第三个点,变为第二个点
        martrix[c][d-i] = martrix[a + i][b];
        //第二个点变为第一个点
        martrix[a + i][b] = temp;
    }
}
//主方法
public void rotate(int[][] martrix){
    int a = 0;
    int b = 0;
    int c = martrix.length - 1 ;
    int d = martrix[0].length - 1;
    while(a < c){//由于这个矩阵是个正方形的,缩小缩到a不越界c
        //交换了一圈然后向里缩一圈
        swapMartrix(martrix, a++, b++, c--, d--);
    }
}

posted on 2022-08-18 22:34  老菜农  阅读(126)  评论(0编辑  收藏  举报

导航