LeetCode 861翻转矩阵后得分详细解法

1. 题目内容

有一个二维矩阵 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. 1 <= A.length <= 20
    2. 1 <= A[0].length <= 20
    3. A[i][j] 是 0 或 1

    2. 分析

    此题是被分类到贪心算法, 所以解决思路就是利用贪心算法, 因为矩阵可以把任意一行或者任意一列的数全部取反, 而要求取得最大的矩阵和。

    求矩阵和的求法 是把每一行的二进制变成10进制, 这就有一个特性: 每一行的第一位为1 要 产生的效益比 它的下面的位之和为1产生的效益要大。 而我可以通过矩阵移动把第一行的第一位都变成1, 这样产生的效益是最大的。

    当第一位都为1时,下面考虑每一列的数字, 对于除了第一列的其他列, 当这一列的1的个数小于0, 则可以通过列移动(取反)使得1的个数大于0, 这是产生的效益是最大的, 而且每一列的交换不会对前面的列或者后面的列产生影响当处理完最后一行 此时得到的矩阵就是 值最大的矩阵了

    所以一共做的处理有两组

    • 第一组处理第一列, 让第一列全变成1, 这样得到此时的最大
    • 第二组 处理随后的列数让里面的1的个数 大于 0, 得到此时的最大

    当处理完全部的列数 因为每一次处理完 都要比原来的值大,而且所有的处理都已完成, 此时的矩阵就是最大值的矩阵。

    3.代码实现

    class Solution {
    public:
        int matrixScore(vector<vector<int>>& A) {
            int row = A.size();
            int col = A[0].size();
            int zeroCount = 0, sum = 0;
            //处理第一列 把它变成 
            for (int i = 0; i < row; i++) {
                if (A[i][0] == 0) {
                    for (int j = 0; j < col; j++) {
                        A[i][j] =  A[i][j] ^ 1;
                    }
                }
            }
            
            for (int j = 0; j < col; j++) {
                //每一列的0个数
                zeroCount = 0;
                for (int i = 0; i < row; i++) {
                    if (A[i][j] == 0) {
                        zeroCount++;
                    }    
                }
                //0个数多 就对此列交换
                if (zeroCount > row/2) {
                    for (int i = 0; i < row; i++) {
                        A[i][j] =  A[i][j] ^ 1;
                    }
                }
            }
            
            //计算结果
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    sum += pow(2, col - j - 1) * A[i][j];
                }
            }
            
            return sum;
            
        }
    };
    

    代码可以更加简化 , 因为我只是需要得到一个值, 不需要得到矩阵, 可以直接通过规律来计算
    代码来自 https://leetcode.com/problems/score-after-flipping-matrix/discuss/143722/C++JavaPython-Easy-and-Concise

        int matrixScore(vector<vector<int>> A) {
        	//res  开始就是 把第一列的1 全部计算起来 (1 << (N - 1)) * M
            int M = A.size(), N = A[0].size(), res = (1 << (N - 1)) * M;
        
            for (int j = 1; j < N; j++) {
                int cur = 0;
                for (int i = 0; i < M; i++) cur += A[i][j] == A[i][0];
                //计算其他列   max(cur, M - cur)表示1的个数
                res += max(cur, M - cur) * (1 << (N - j - 1));
            }
            return res;
        }
    

    4. 总结

    • 找到题目特性, 找到能贪心的点

    5. 学习贪心算法

    从零开始学贪心算法

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

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值