It's our wits that make us men.

832.翻转图像

Posted on By eatMelon-Masses

给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。

水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。

反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。

示例 1:

输入: [[1,1,0],[1,0,1],[0,0,0]]
输出: [[1,0,0],[0,1,0],[1,1,1]]
解释: 首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]];
     然后反转图片: [[1,0,0],[0,1,0],[1,1,1]]

示例 2:

输入: [[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]]
输出: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
解释: 首先翻转每一行: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]];
     然后反转图片: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]

说明:

  • 1 <= A.length = A[0].length <= 20
  • 0 <= A[i][j] <= 1

最近已经做了好几道关于数组的题啦,废话少说进入正题。

题意:

  • 数组逆序
  • 元素值取反

    思路1

       新建一个大小一样的二维数组,然后对元素复制转移。

    注意:

    两层for循环的内循环遍历顺序从列尾向前遍历

  • 元素取反:公式(n+1)%2
  • 贴上代码
    public int[][] flipAndInvertImage(int[][] A) {
              int[][] b = new int[A.length][A[0].length];//新建一个同样大小的数组b
              int rowN=A.length;//数组的行数
              int colN=A[0].length;//数组的列数
          for (int i = 0; i <=A.length-1 ; i++) {
              for (int j = A[0].length-1; j >=0;j-- ) {//注意此处列循环的初始条件和判出条件
                  b[i][colN-1-j] = (A[i][j]+1)%2;//元素值取反复制到新的数组当中
              }
          }
          return b;
      }
    

     最终测试运行通过

excuse me? 

LeetCode平台提交代码,跑85个用例耗时28ms,战胜20%的其他用户。

时间复杂度:(n^2),效率太低。想想优化方案

思路2.

还是需要做两层循环遍历,但是如果是逆序的话我们可以对掉数组头和对应数组尾的元素,这样的话只需要循环遍历整个数组一半的元素

注意

数组列中间的位置为:列数/2   中间位置左边的元素游标为0~(列数/2-1)对应中间位置右边的游标:(列数/2+1) ~(列数-1)      当列数为偶数时:需要单独对每一行中间值取反,这是我们可以做一个标记,然后在外层循环遍历时对每一行中间元素单独取反操作。 代码如下

    public int[][] flipAndInvertImage(int[][] A) {

        int colN=A[0].length;
        boolean sign =colN%2==0?false:true;//标记当前列数是否为奇数
        for (int i = 0; i <=A.length-1 ; i++) {
            for (int j = colN/2-1; j >=0;j-- ) {
                //注意内循环的条件
                A[i][j]=(A[i][j]+1)%2;//中间位置左边的元素取非
                int temp=(A[i][colN-1-j]+1)%2;//对应右边的元素取非,存在临时变量中
                A[i][colN-1-j]=A[i][j];//对掉元素值
                A[i][j]=temp;

            }
            //在外层循环中
            if (sign) A[i][colN/2]=(A[i][colN/2]+1)%2;//如果是奇数列中间值取反
        }
        return A;
    }

最终测试运行通过

LeetCode平台提交代码,跑85个用例耗时6ms,战胜97%的其他用户。
时间复杂度:(n^2)/2,稍微优化了下
如果大家有更好的优化方案,欢迎贴出代码!