Leetcode 3240#
原题链接
题目要求所有的行和列都是回文,又限制1的个数需要被4整除。
- 行列均回文即要求
$$
arr[i][j] = arr[m-1-i][j] = arr[i][n-1-j] = arr[m-1-i][n-1-j]
$$
遍历数组,计算$cnt1=arr[i][j] + arr[n-1-i][j] + arr[i][n-1-j] + arr[n-1-i][n-1-j]$的和,和即为1的个数,将$min(result, cnt1)$计入结果。
- 如果为偶数行偶数列,此时已经计算完毕,反之
- 中心元素必须为0,$result+=arr[m/2][n/2]$, $arr[m/2][n/2]=0$时不会计入修改次数所以直接相加即可
- 计算中心行或中心列,先计算匹配的1个数,记为$cnt$,计算需要修改的对数$diff$
- $cnt%4==0$ 1的个数能被4整除,$diff$对全改为0,计入结果
- $cnt%4==2$ 1的个数不能4整除, $diff==0$,将$cnt%4$余下的两个改为0即可,$diff!=0$ 选择diff中的一对改为1,其余的改为0即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
class Solution {
public:
int minFlips(vector<vector<int>>& grid) {
/*
grid[i][j]=grid[m-i-1][j] 列相等
grid[i][j]=grid[i][n-j-1] 行相等
grid[i][n-j-1] = grid[m-i-1][n-j-1]
*/
int m = grid.size(), n = grid[0].size();
int result = 0;
for (int i = 0; i < m / 2; i++) {
for (int j = 0; j < n / 2; j++) {
int cnt1 = grid[i][j] + grid[i][n - 1 - j] +
grid[m - 1 - i][j] + grid[m - 1 - i][n - 1 - j]; // 计算的结果就是1的个数,将其变为0即可
result += min(cnt1, 4 - cnt1); // 全变为1或全变为0
}
}
if (m % 2 && n % 2) {
result += grid[m / 2][n / 2]; // 确保中间为0,如果为0,+0不会变化,如果为1,+1变换次数+1
}
/* 单独讨论奇数行和奇数列
镜像位置如果都一样,能不改就不改,先统计不改的位置有多少个1,
记作cnt1, 需要修改的为diff 分类讨论
cnt1%4 = 0 diff对全部改为0 or
cnt1%4 = 2 diff>0 选择一对,改为1
diff==0 选择原来不改的一对,改为0即可
*/
// 有奇数行
int diff = 0, cnt1 = 0;
if (m % 2) {
for (int i = 0; i < n / 2; i++) {
if (grid[m / 2][i] != grid[m / 2][n - 1 - i])
diff++;
else
cnt1 += grid[m / 2][i] * 2;
}
}
// 有奇数列
if (n % 2) {
for (int i = 0; i < m / 2; i++) {
if (grid[i][n / 2] != grid[m - 1 - i][n / 2])
diff++;
else
cnt1 += grid[i][n / 2] * 2;
}
}
// 如果一致的1的个数能够整除4 返回 result+diff 即将diff中不为0的改为0
if (cnt1 % 4 == 0)
return result + diff;
// 如果一致的1的个数无法整除4 返回 result+(cnt1%4)+diff
// 将整除4余下的个数全改为1即可
return result + (diff ? diff : cnt1 % 4);
// return result + (diff ? diff : cnt1 % 4);
}
};
|
时间复杂度#
- 遍历数组,复杂度为O(m*n)
空间复杂度#
- 只需要常数量的变量存储结果,所以未O(1)