861. 翻转矩阵后的得分

贪心

每次都改变一行或者一列,将0和1互换
若干次操作之后,按照每行的数统计结果,用二进制表示

首先高位的1会大于所有低位的1之和,如1000 = 8 > 0111 = 7
那么我们贪心的策略就有了,其次为了尽可能的构造高位1,对于第一列,如果翻转后1的个数多,那么就翻转,由于此时保证了最高位出现了最多的1,那么我们接下来依次检查每一行,如果这一行首尾不是0,那么就翻转这一行

然后我们用列变换再次检查其它列的元素,如果翻转后1变多,那么翻转列

总结一下策略

  1. 检查第一列,如果翻转后1变多,那么翻转
  2. 检查每一行,如果高位不是1,那么翻转
  3. 检查剩下的列(2到n),如果翻转后1变多,那么翻转

一道很好的贪心题目

class Solution:
    def matrixScore(self, A: List[List[int]]) -> int:
            # 行和列
        row, col = len(A), len(A[0])
        # 统计第一列的1
        cnt = sum([A[i][0] for i in range(row)])
        # 如果翻转后1变多
        if cnt <= row // 2:
            for i in range(row):
                A[i][0] = 1 if A[i][0] == 0 else 0

        # print(A)

        # 对于每一行,如果第一个元素不是1,翻转这一行
        for i in range(row):
            if A[i][0] != 1:
                for j in range(col):
                    A[i][j] = 1 if A[i][j] == 0 else 0

        # print(A)

        # 对于剩下的每一列,如果翻转后1变多,那么就翻转
        for j in range(1, col):
            cnt = sum([A[i][j] for i in range(row)])
            if cnt <= row // 2:
                for i in range(row):
                    A[i][j] = 1 if A[i][j] == 0 else 0

        # print(A)
        ans = 0
        for i in range(row):
            inx = 2
            for j in range(col - 1, -1, -1):
                ans += A[i][j] * (inx ** (col - j - 1))

        return ans

再分析一下,我们要保证最高位都是1,那么第一步检查翻转列就是多余的,直接检查每一行即可

class Solution:
    def matrixScore(self, A: List[List[int]]) -> int:
            # 行和列
        row, col = len(A), len(A[0])

        # 对于每一行,如果第一个元素不是1,翻转这一行
        for i in range(row):
            if A[i][0] != 1:
                for j in range(col):
                    A[i][j] = 1 if A[i][j] == 0 else 0

        # print(A)

        # 对于剩下的每一列,如果翻转后1变多,那么就翻转
        for j in range(1, col):
            cnt = sum([A[i][j] for i in range(row)])
            if cnt <= row // 2:
                for i in range(row):
                    A[i][j] = 1 if A[i][j] == 0 else 0

        # print(A)
        ans = 0
        for i in range(row):
            inx = 2
            for j in range(col - 1, -1, -1):
                ans += A[i][j] * (inx ** (col - j - 1))

        return ans

在这里插入图片描述

不用移动矩阵的贪心

主要是贪心策略加上一些trick,直接用二进制的方法来统计每一位上1的贡献

在这里插入图片描述

class Solution {
public:
    int matrixScore(vector<vector<int>>& A) {
        int m = A.size(), n = A[0].size();
        int ret = m * (1 << (n - 1));

        for (int j = 1; j < n; j++) {
            int nOnes = 0;
            for (int i = 0; i < m; i++) {
                if (A[i][0] == 1) {
                    nOnes += A[i][j];
                } else {
                    nOnes += (1 - A[i][j]); // 如果这一行进行了行反转,则该元素的实际取值为 1 - A[i][j]
                }
            }
            int k = max(nOnes, m - nOnes);
            ret += k * (1 << (n - j - 1));
        }
        return ret;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/score-after-flipping-matrix/solution/fan-zhuan-ju-zhen-hou-de-de-fen-by-leetc-cxma/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

思想就是最大的矩阵第一列肯定都是1,然后直接加上首位的贡献,然后对于剩下的列,统计1的个数(如果首位是0,意味着这一行要反转,需要对应操作),然后我们用位移的方法加上每个1的贡献即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值