按列翻转得到最大值等行数

标签: 数组 哈希表 矩阵

难度: Medium

给定 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

Submission

运行时间: 73 ms

内存: 19.0 MB

class Solution:
    def maxEqualRowsAfterFlips(self, matrix: List[List[int]]) -> int:
        n, m = len(matrix), len(matrix[0])
        d = Counter()
        for i in range(n):
            if matrix[i][0]:
                for k in range(m):
                    matrix[i][k] ^= 1
            d[tuple(matrix[i])] += 1  
        return max(d.values())

Explain

此题的核心思路在于将每一行通过列翻转变为全0或全1,以此来最大化行内值相同的行数。因此,可以利用翻转的特性来规范化行的表示。例如,如果某行的第一个元素为1,我们可以翻转整行以使其首元素变为0,从而得到统一的行表示。通过统计每种行表示出现的频次,可以找到最多可以通过翻转得到相同元素的行数。使用字典来记录每种行的出现次数,并通过翻转来确保每一行的第一个元素始终为0,这样只需要比较剩余的部分即可。

时间复杂度: O(n*m)

空间复杂度: O(m*n)

class Solution:
    def maxEqualRowsAfterFlips(self, matrix: List[List[int]]) -> int:
        n, m = len(matrix), len(matrix[0])  # 获取行数n和列数m
        d = Counter()  # 初始化计数器
        for i in range(n):  # 遍历每一行
            if matrix[i][0]:  # 如果当前行的第一个元素是1
                for k in range(m):  # 遍历这一行的每个元素
                    matrix[i][k] ^= 1  # 将1翻转为0,0翻转为1
            d[tuple(matrix[i])] += 1  # 将翻转后的行转换为元组并计数
        return max(d.values())  # 返回出现最多的行的次数

Explore

选择将行的第一个元素统一为0是为了确保行的表示具有一致性和可比性。将第一个元素设为0是一个规范化的过程,使每一行都基于相同的起始条件进行比较和计数。这样做的好处是简化了逻辑,因为0通常在数字操作中作为基础更为直观和统一。此外,无论选择0还是1作为规范化的目标,都不会影响最终结果,因为翻转操作是可逆的,关键在于保持一致的比较标准。

翻转操作不会对全0或全1行产生不利影响。对于全0行,如果第一个元素已经是0,那么整行不会进行翻转,维持其原样。对于全1行,整行将被翻转成全0,这是一种有效的转换,旨在统一行的格式。这种方法确保了即使原始行是全0或全1,通过翻转可以使所有行尽可能地相似,从而最大化相同行数。

将行数据转换为元组并用作字典键确实可能在处理大规模数据时产生性能瓶颈。首先,元组是不可变的,需要在每次迭代时创建新的元组对象,这会增加内存使用。其次,如果矩阵的列数很大,元组将包含大量元素,这会增加哈希计算的复杂度和存储空间。在面对非常大的数据集时,可以考虑使用更高效的数据结构或优化算法,例如使用位操作和整数哈希来减少内存使用和提高处理速度。

是的,代码实现中确实考虑了各行翻转后可能相等的情况。通过将所有行的第一个元素统一为0,并对需要翻转的行进行实际的翻转操作,确保了即使原始行不同,只要它们翻转后相同,就会被统计为相同的行。这种方法通过对行的统一表示和计数,能够有效地识别和统计那些原始不同但翻转后相同的行,从而最大化可以通过翻转得到相同元素的行数。