算法练习每日一题:翻转矩阵后的得分

861. 翻转矩阵后的得分

有一个二维矩阵 A 其中每个元素的值为 0 或 1 。

移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0。

在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。

返回尽可能高的分数。

示例:

输入:[[0,0,1,1],[1,0,1,0],[1,1,0,0]]
输出:39
解释:
转换为 [[1,1,1,1],[1,0,0,1],[1,1,1,1]]
0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39

提示:

1 <= A.length <= 20
1 <= A[0].length <= 20
A[i][j] 是 0 或 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/score-after-flipping-matrix

class Solution:
    def matrixScore(self, A):
        rst = 0
        R, C = len(A),len(A[0])
        for c in range(0, C):
            col = 0
            for r in range(0, R):
                col += A[r][c] ^ A[r][0]
            rst += max(col, R-col)*(2**(C-1-c))
        return rst
A = [[0,0,1,1],[1,0,1,0],[1,1,0,0]]
print(Solution().matrixScore(A))
39

题解

  • 分析

注意到将一行或者一列翻转两次及以上是没有意义的,因为翻转两次等价于没有进行任何翻转。因此每一行和每一列最多被翻转了一次。
我们首先枚举每一行是否被翻转,对于一个 R 行 C 列的矩阵,可能的翻转情况有 2^R 种。随后对于每一列,1 的个数应该越多越好。如果某一列当前有 k 个 1,那么翻转后将会有 R - k 个 1,我们比较 k 和 R - k 的大小,就可以判断这一列是否需要翻转。

对于任意一行而言,如果这一行的第一个数 1,那么它的分数一定会比不是 1 要高。这是因为第一个 1 代表了 2C−12^{C-1}2C−1,而如果第一位是 0,那么即使后面所有的位置都是 1,这一行的值最多也是 2C−2+⋯+21+20=2C−1−12^{C-2} + \cdots + 2^1 + 2^0 = 2^{C-1}-12C−2+⋯+21+20=2C−1−1,小于 2C−12^{C-1}2C−1。因此我们不需要枚举每一行是否需要翻转,而是变为:如果该行的第一位是 0,则翻转,否则不翻转。

  • 算法

设矩阵有 R 行 C 列,我们用一个 R 位的二进制数 state 表示每一行是否被翻转,state 的范围是 [0 … 2^R)。

如果该行的第一位是 0 则翻转,否则不翻转(这可以通过代码 A[r][c] ^= A[r][0] 直接实现),并在行翻转完毕后,对第一列进行翻转,这样也使得每一行的第一位都是 1。然后我们枚举每一列是否翻转.
要理解位移运算!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值