代码实现时,我们可以用二进制表示集合,二进制的第 i 位为 1 表示 i 在集合中,为 0 表示 i 不在集合中。这样可以用二进制枚举集合,同时把 mat 的每一行也用二进制表示,从而做到 O(1) 判断行中的所有 1 是否被覆盖。
[sol1-Python3]
1 2 3 4 5 6 7 8
classSolution: defmaximumRows(self, mat: List[List[int]], cols: int) -> int: ans = 0 mask = [sum(v << j for j, v inenumerate(row)) for i, row inenumerate(mat)] forsetinrange(1 << len(mat[0])): ifset.bit_count() == cols: # 集合的大小等于 cols,符合题目要求 ans = max(ans, sum(row & set == row for row in mask)) # row & set = row 表示 row 是 set 的子集,所有 1 都被覆盖 return ans
funcmaximumRows(mat [][]int, cols int) (ans int) { m, n := len(mat), len(mat[0]) mask := make([]int, m) for i, row := range mat { for j, v := range row { mask[i] |= v << j } } for set := 0; set < 1<<n; set++ { if bits.OnesCount(uint(set)) != cols { // 跳过大小不等于 cols 的集合 continue } cnt := 0 for _, row := range mask { if row&set == row { // row 是 set 的子集,所有 1 都被覆盖 cnt++ } } ans = max(ans, cnt) } return }
funcmax(a, b int)int { if b > a { return b }; return a }
时间复杂度:O(m\cdot C_{n}^{\textit{cols} })。其中 m 为 mat 的行数,n 为 mat 的列数。
空间复杂度:O(m)。
[sol2-Python3]
1 2 3 4 5 6 7 8 9 10 11
classSolution: defmaximumRows(self, mat: List[List[int]], cols: int) -> int: ans = 0 mask = [sum(v << j for j, v inenumerate(row)) for i, row inenumerate(mat)] set = (1 << cols) - 1 whileset < 1 << len(mat[0]): ans = max(ans, sum(row & set == row for row in mask)) # row & set = row 表示 row 是 set 的子集,所有 1 都被覆盖 lb = set & -set x = set + lb set = (set ^ x) // lb >> 2 | x return ans
funcmaximumRows(mat [][]int, cols int) (ans int) { m, n := len(mat), len(mat[0]) mask := make([]int, m) for i, row := range mat { for j, v := range row { mask[i] |= v << j } } for set := 1<<cols - 1; set < 1<<n; { cnt := 0 for _, row := range mask { if row&set == row { // row 是 set 的子集,所有 1 都被覆盖 cnt++ } } ans = max(ans, cnt) lb := set & -set x := set + lb // 下式等价于 set = (set^x)/lb>>2 | x set = (set^x)>>bits.TrailingZeros(uint(lb))>>2 | x } return }
funcmax(a, b int)int { if b > a { return b }; return a }