矩阵变换

矩阵

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   老菜农  阅读(139)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律

导航

统计信息

点击右上角即可分享
微信分享提示