|
| 1 | +#### [832. 翻转图像](https://leetcode-cn.com/problems/flipping-an-image/) |
| 2 | + |
| 3 | +给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。 |
| 4 | + |
| 5 | +水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。 |
| 6 | + |
| 7 | +反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。 |
| 8 | + |
| 9 | +``` |
| 10 | +示例 1: |
| 11 | +
|
| 12 | +输入:[[1,1,0],[1,0,1],[0,0,0]] |
| 13 | +输出:[[1,0,0],[0,1,0],[1,1,1]] |
| 14 | +解释:首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]]; |
| 15 | + 然后反转图片: [[1,0,0],[0,1,0],[1,1,1]] |
| 16 | +示例 2: |
| 17 | +
|
| 18 | +输入:[[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]] |
| 19 | +输出:[[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]] |
| 20 | +解释:首先翻转每一行: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]]; |
| 21 | + 然后反转图片: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]] |
| 22 | +
|
| 23 | +
|
| 24 | +提示: |
| 25 | +
|
| 26 | +1 <= A.length = A[0].length <= 20 |
| 27 | +0 <= A[i][j] <= 1 |
| 28 | +``` |
| 29 | + |
| 30 | +#### 解题思路(双指针+一次遍历) |
| 31 | + |
| 32 | +最直观的做法是首先对矩阵 A 的每一行进行水平翻转操作,然后对矩阵中的每个元素进行反转操作。该做法需要遍历矩阵两次。 |
| 33 | + |
| 34 | +是否可以只遍历矩阵一次就完成上述操作?答案是肯定的。 |
| 35 | + |
| 36 | +假设矩阵的行数和列数都是 n,考虑列下标 `left` 和 `right`,其中 `left<right` 且 `left+right=n−1`,当 `0≤i<n` 时,对第 i 行进行水平翻转之后,`A[i][left] `和 `A[i][right] `的元素值会互换,进行反转之后,`A[i][left] `和 `A[i][right] `的元素值都会改变。 |
| 37 | + |
| 38 | +具体而言,考虑以下四种情况。 |
| 39 | + |
| 40 | +- 情况一:`A[i][left] `=0, `A[i][right] `=0。对第 i 行进行水平翻转之后,`A[i][left] `=0, `A[i][right] `=0。进行反转之后,`A[i][left] `=1, `A[i][right] `=1。 |
| 41 | + |
| 42 | +- 情况二:`A[i][left] `=1, `A[i][right] `=1。对第 i 行进行水平翻转之后,`A[i][left] `=1, `A[i][right] `=1。进行反转之后,`A[i][left] `=0, `A[i][right] `=0。 |
| 43 | + |
| 44 | +- 情况三:`A[i][left] `=0, `A[i][right] `=1。对第 i 行进行水平翻转之后,`A[i][left] `=1, `A[i][right] `=0。进行反转之后,`A[i][left] `=0, `A[i][right] `=1。 |
| 45 | + |
| 46 | +- 情况四:`A[i][left] `=1, `A[i][right] `=0。对第 ii 行进行水平翻转之后,`A[i][left] `=0, `A[i][right] `=1。进行反转之后,`A[i][left] `=1, `A[i][right] `=0。 |
| 47 | + |
| 48 | +情况一和情况二是 `A[i][left] ` = `A[i][right] `的情况。在进行水平翻转和反转之后,`A[i][left] `和`A[i][right] ` 的元素值都发生了改变,即元素值被反转。 |
| 49 | + |
| 50 | +情况三和情况四是 `A[i][left] ` ≠ `A[i][right] `的情况。在进行水平翻转和反转之后,`A[i][left] `和`A[i][right] `的元素值都发生了两次改变,恢复原状。 |
| 51 | + |
| 52 | +因此,可以遍历矩阵一次即完成水平翻转和反转。 |
| 53 | + |
| 54 | +- 遍历矩阵的每一行。对于矩阵的第 i 行,初始化 `left=0`和`right=n−1`,进行如下操作: |
| 55 | + - 当 `left<right` 时,判断 `A[i][left] `和`A[i][right] `是否相等,如果相等则对`A[i][left] `和`A[i][right] `的值进行反转,如果不相等则不进行任何操作; |
| 56 | + - 将 `left` 的值加 1,将 `right` 的值减 1,重复上述操作,直到 `left≥right`; |
| 57 | + |
| 58 | +**如果 n 是奇数,则上述操作结束时,`left` 和 `right` 的值相等,都指向第 i 行的中间元素,此时需要对中间元素的值进行反转。** |
| 59 | + |
| 60 | +**代码演示(Golang)** |
| 61 | + |
| 62 | +```go |
| 63 | +func flipAndInvertImage(A [][]int) [][]int { |
| 64 | + for _, row := range A { |
| 65 | + left, right := 0, len(row)-1 |
| 66 | + for left < right { |
| 67 | + if row[left] == row[right] { |
| 68 | + row[left] ^= 1 |
| 69 | + row[right] ^= 1 |
| 70 | + } |
| 71 | + left++ |
| 72 | + right-- |
| 73 | + } |
| 74 | + // n 是奇数,left和right的值相等,都指向第 i 行的中间元素,此时需要对中间元素的值进行反转。 |
| 75 | + if left == right { |
| 76 | + row[left] ^= 1 |
| 77 | + } |
| 78 | + } |
| 79 | + return A |
| 80 | +} |
| 81 | + |
| 82 | +``` |
| 83 | + |
| 84 | +> 时间复杂度:O(n<sup>2</sup>),其中 n 是矩阵 A 的行数和列数。需要遍历矩阵一次,进行翻转操作。 |
| 85 | +> |
| 86 | +> 空间复杂度:O(1)。除了返回值以外,额外使用的空间为常数。 |
| 87 | +> |
0 commit comments