翻转图像

描述

力扣第 832 题。给定一个二进制矩阵 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 为例子

21 反转图像.png

  • 第一步,获取第一行数据 1,1,0

  • 将第一个位置的元素和最后一个位置的元素替换位置,因为是 3 个元素,所以第二个位置的元素不需要改变,得到如下结果:

22 反转图像.png

  • 得到了水平翻转的结果,然后将其进行反转,即将 0 变成 1 ,1 变成 0。所以得到结果 1,0,0。

23 反转图像.png

  • 第二行,第三行的数据和第一行的操作方式一样,先将第一列的数据和最后一列的数据替换,然后将 0 变成 1 ,1 变成 0。

在上面的替换操作过程中,我们需要掌握以下技巧:

  1. 水平翻转的时候,我们需要知道当前行的数据是偶数个还是基数个,如果是基数个,那么中间的那个数就不需要替换位置,如果是偶数个,那么直接遍历一半的数据,让剩下的数据与遍历到的数据替换。水平替换的时候,左边下标替换的数索引与右边下标替换的数索引相加和是一样的。
  2. 因为是二进制替换,等行数据翻转后,直接将 0 变成 1 ,1 变成 0 即可。

代码具体实现

Java语言实现

class Solution { public int[][] flipAndInvertImage(int[][] A) { //每行数组的最右侧数据下标 int rightIndex = A[0].length - 1; //每行数组下标的中间位置,每次循环的时候,只需要循环到中间位置,进行替换即可 int dividColCount = A[0].length / 2; //判断每行记录的个数是基数还是偶数 int perCol = A[0].length % 2; for (int i = 0; i < A.length; i++) { for (int j = 0; j < dividColCount; j++) { //取出一半长度左边位置的数据 int leftValue = A[i][j]; //取出右侧对应的位置数据 int rightValue = A[i][rightIndex - j]; //左边数据用右侧数据赋值,并且进行反转 A[i][j] = rightValue == 0 ? 1 : 0; //右边数据用左侧的数据赋值,并且进行反转 A[i][rightIndex - j] = leftValue == 0 ? 1 : 0; } //如果每行的数组长度是基数个数,则需要将中间位置的数据进行反转图片操作 if (perCol != 0) { A[i][dividColCount] = A[i][dividColCount] == 0 ? 1 : 0; } } return A; } }

Go语言实现

func flipAndInvertImage(A [][]int) [][]int { //每行数组的最右侧数据下标 rightIndex := len(A[0]) - 1 //每行数组下标的中间位置,每次循环的时候,只需要循环到中间位置,进行替换即可 dividColCount := len(A[0]) / 2 //判断每行记录的个数是基数还是偶数 perCol := len(A[0]) % 2 for i := 0; i < len(A); i++ { for j := 0; j < dividColCount; j++ { //取出一半长度左边位置的数据 leftValue := A[i][j] //取出右侧对应的位置数据 rightValue := A[i][rightIndex - j] //左边数据用右侧数据赋值,并且进行反转 A[i][j] = changeNum(rightValue) //右边数据用左侧的数据赋值,并且进行反转 A[i][rightIndex - j] = changeNum(leftValue) } //如果每行的数组长度是基数个数,则需要将中间位置的数据进行反转图片操作 if perCol != 0 { A[i][dividColCount] = changeNum(A[i][dividColCount]) } } return A; } //将数据进行反转 func changeNum(a int) int{ if a == 0 { return 1 }else { return 0 } }