1072.按列翻转得到最大值等行数:不错的思维题!

【LetMeFly】1072.按列翻转得到最大值等行数

力扣题目链接:https://leetcode.cn/problems/flip-columns-for-maximum-number-of-equal-rows/

给定 m x n 矩阵 matrix 。

你可以从中选出任意数量的列并翻转其上的 每个 单元格。(即翻转后,单元格的值从 0 变成 1,或者从 1 变为 0 。)

返回 经过一些翻转后,行与行之间所有值都相等的最大行数 。

 

示例 1:

输入:matrix = [[0,1],[1,1]]
输出:1
解释:不进行翻转,有 1 行所有值都相等。

示例 2:

输入:matrix = [[0,1],[1,0]]
输出:2
解释:翻转第一列的值之后,这两行都由相等的值组成。

示例 3:

输入:matrix = [[0,0,0],[0,0,1],[1,1,0]]
输出:2
解释:翻转前两列的值之后,后两行由相等的值组成。

 

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 300
  • matrix[i][j] == 0 或 1

方法一:思维

首先这道题的中文描述有点错误。题目要求的是:一行之内的元素全相等 的 行数 的最大值。

怎么个翻转法呢?我可以选取某些列,将这些列的0变成1,1变成0。

试想这样(完全相同)的多行:

1
2
3
4
011010
011010
011010
...

我们只需要把第2、3、5列翻转,就能得到:

1
2
3
4
000000
000000
000000
...

这些原本完全相同的行,每一行都变成了0

试想这样(完全相反)的两行:

1
2
011010
100101

我们只需要把第2、3、5列翻转,就能得到:

1
2
000000
111111

这些完全相反的行,有的变成了全0,有的变成了全1

有没有发现,上面两种情况,我们都是反转的第“2,3,5”行,最终得到的结果是:这些行要么全0,要么全1

也就是说:原本完全相同或完全相反的行,可以通过题目描述的翻转操作,使得这些行变得要么全0要么全1

而题目问的,就是“全0行”和“全1行”的最大行数和

因此,我们只需要将完全相同的行 或 完全相反的行 聚成一类,最大的“聚合块”的大小即为答案。

例如:

1
2
3
4
5
6
7
0 0 0
1 1 1
0 0 0
0 1 0
1 1 1
0 0 1
1 1 0

可以聚合成三块:

1
2
3
1. [0, 0, 0], [1, 1, 1], [0, 0, 0], [1, 1, 1]
2. [0, 1, 0]
3. [0, 0, 1], [1, 1, 0]

第1块最大有四个即为答案。

因此剩下的问题就是:如何将完全相同的行或完全相反的行聚成一类?(现在完全不用考虑题目说的什么翻转,什么相等了)

不失一般性,我们可以让每一行的第一个元素全部变成0。

  • 如果某一行第一个元素本来就是0,那么这一行就完全不变
  • 否则(某行第一个元素是1),就将这一行的每个元素都翻转(0变1,1变0)

注意这里的翻转和题目中的翻转没有任何关系,这里翻转只是为了将完全相反的行变成完全相同的行从而用来统计

这样,问题就变成了:将完全相同的行聚成一类,最大的“聚合块”的大小是多少

使用一个哈希表就能很方便地解决了。

  • 时间复杂度$O(n\times m)$,其中$matrix$的大小为$n\times m$
  • 空间复杂度$O(n\times m)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
int maxEqualRowsAfterFlips(vector<vector<int>>& matrix) {
unordered_map<vector<bool>, int> ma; // 哈希表
int n = matrix.size(), m = matrix[0].size();
int ans = 0;
for (int i = 0; i < n; i++) {
vector<bool> thisLine(m); // 这一行
for (int j = 0; j < m; j++) { // 使用异或操作,[行首, 本元素] -> 最终结果:[0, 0] -> 0,[0, 1] -> 1,[1, 0] -> 1,[1, 1] -> 0
thisLine[j] = matrix[i][j] ^ matrix[i][0];
}
ma[thisLine]++;
ans = max(ans, ma[thisLine]);
}
return ans;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# from typing import List
# from collections import defaultdict

class Solution:
def maxEqualRowsAfterFlips(self, matrix: List[List[int]]) -> int:
ma = defaultdict(int)
n, m = len(matrix), len(matrix[0])
ans = 0
for i in range(n):
thisLine = ''
for j in range(m):
thisLine += chr(ord('0') + matrix[i][j] ^ matrix[i][0])
ma[thisLine] += 1
ans = max(ans, ma[thisLine])
return ans

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/130680800


1072.按列翻转得到最大值等行数:不错的思维题!
https://blog.letmefly.xyz/2023/05/15/LeetCode 1072.按列翻转得到最大值等行数/
作者
Tisfy
发布于
2023年5月15日
许可协议