详细解LeetCode 1284. Minimum Number of Flips to Convert Binary Matrix to Zero Matrix

题目链接 https://leetcode.com/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix/

大致题意

给你一个 m x n 的二进制矩阵 mat,每一步,你可以选择一个单元格并将它反转(反转表示 0 变 1 ,1 变 0 )。如果存在和它相邻的单元格,那么这些相邻的单元格也会被反转。(注:相邻的两个单元格共享同一条边。)

请你返回将矩阵 mat 转化为全零矩阵的 最少反转次数,如果无法转化为全零矩阵,请返回 -1。

二进制矩阵的每一个格子要么是 0 要么是 1 ,全零矩阵是所有格子都为 0 的矩阵。

具体例子见原题链接

题解:首先考虑的是暴力求解,复杂度O(mn⋅2^mn),暴力枚举哪些位置需要反转,一共有 2^mn 种方案,对于每种方案,验证最终是否为全 0,找到反转次数最少的方案。

但是随后可以发现我们发现,如果确定了第一行(或第一列)反转哪些位置,则之后反转的位置就都可以确定,举个例子,假设我们已经反转了第一行的某些位置,我们从第二行开始一直到最后一行,如果发现当前位置的上一行是 1,则当前位置需要进行反转,简单来说就是,对第一行遍历所有可能,也就是对每一个位置都选择是否翻转,一共2^n种可能,然后从第二行开始,一单发现某一个位置上边的位置是1,那么我们就翻转这个格子,这样持续下去可以确保每行执行完,该行以上的全是0,判断是否全部翻转为0的依据是判断下最后一行是否也都已经变成了 0。

这样上述方案的时间复杂度是O(m*n*2^n),时间上大大缩小了

下边是实现代码,配有充足的注释

class Solution {
public:
    int minFlips(vector<vector<int>>& mat) {
        int m = mat.size(),n = mat[0].size();
        //要翻转的五个位置数组
        int dx[5] = {0,0,1,0,-1};
        int dy[5] = {0,1,0,-1,0};
        //最后的返回结果,初始化为一个大值
        int ans = m*n+1;
        //K从0到1<<n,一共2^n
        for(int K = 0;K<(1<<n);K++){
            //对于每一个K定义一个局部结果
            int cnt = 0;
            //接下来定义一个temp数组,这里要说的是,我们可以对
            //原数组翻转成0也可以将0数组翻转成原数组
            //这二者是等价的
            vector<vector<int>>temp(m,vector<int>(n,0));
            //开始处理第一行
            for(int j = 0;j<n;j++){
                if((K>>j)&1){
                    cnt++;
                    for(int k = 0;k<5;k++){
                        int x = 0+dx[k],y = j+dy[k];
                        if(x<0||x>=m||y<0||y>=n)continue;
                        //翻转全部和1异或
                        temp[x][y]^=1;
                    }
                }
            }
            //处理后边行
            for(int i = 1;i<m;i++)
                for(int j = 0;j<n;j++){
                    //发现上边位置需要翻转
                    if(temp[i-1][j]^mat[i-1][j]){
                        cnt++;
                        
                        for(int k = 0;k<5;k++){
                            int x = i+dx[k],y = j+dy[k];
                            if(x<0||x>=m||y<0||y>=n)continue;
                            temp[x][y]^=1;
                        }
                    }
                }
            
            int flag = 1;
            //检验最后一行是否为0
            for(int j = 0;j<n;j++)
                if(temp[m-1][j]^mat[m-1][j]){
                    flag = 0;
                    break;
                }
            //满足条件取小值
            if(flag)ans = min(ans,cnt);
            
        }
        //没有满足条件的情况下返回-1
        if(ans==m*n+1)ans = -1;
        return ans;
    }
};

因为按位操作方面比较薄弱,所以把这个记录在这里,供以后自己复习或者其他人学习用,运行结果比想象中要好一些

参考链接:

https://leetcode.com/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix/

 https://www.acwing.com/solution/LeetCode/content/6856/

发布了31 篇原创文章 · 获赞 38 · 访问量 5035

猜你喜欢

转载自blog.csdn.net/qq_41685265/article/details/104153030