每日一题3239.最少翻转次数使二进制矩阵回文;

本题出自LeetCode每日一题3239.最少翻转次数使二进制矩阵回文,初看想着就是一道暴力破解,双指针强硬遍历一横一竖


题目

给你一个 m x n 的二进制矩阵 grid 。

如果矩阵中一行或者一列从前往后与从后往前读是一样的,那么我们称这一行或者这一列是 回文 的。

你可以将 grid 中任意格子的值 翻转 ,也就是将格子里的值从 0 变成 1 ,或者从 1 变成 0 。

请你返回 最少 翻转次数,使得矩阵 要么 所有行是 回文的 ,要么所有列是 回文的 。

示例 1:

**输入:**grid = \[1,0,0,0,0,0,0,0,1]

**输出:**2

解释:

将高亮的格子翻转,得到所有行都是回文的。

示例 2:

**输入:**grid = \[0,1,0,1,0,0]

**输出:**1

解释:

将高亮的格子翻转,得到所有列都是回文的。

示例 3:

**输入:**grid = \[1,0]

**输出:**0

解释:

所有行已经是回文的。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m * n <= 2 * 105
  • 0 <= grid[i][j] <= 1

解题思路

这个问题要求我们在给定的 m x n 的二进制矩阵 grid 中,通过最少的翻转次数(即把某个位置的 0 变成 1 或者 1 变成 0),让所有的行或所有的列都成为回文。要解决这个问题,我们可以采取以下步骤:

  1. 定义回文:首先明确什么是回文。对于行来说,如果一个行从左到右读和从右到左读是一样的,那么这个行就是回文的。同样的规则适用于列。

  2. 计算翻转次数:

    • 对于每一行,我们可以通过比较第 i 列和第 n-i-1 列(从左端和右端同时向中间靠拢)来检查是否需要翻转。如果这两个位置上的数字不同,则至少需要一次翻转才能使该行成为回文。
    • 同样地,对于每一列,我们可以通过比较第 i 行和第 m-i-1 行来检查是否需要翻转,以确保该列是回文的。
  3. 选择最小的翻转次数:我们需要分别计算出使所有行成为回文所需的最少翻转次数,以及使所有列成为回文所需的最少翻转次数。最终的结果应该是这两者中的较小值。


题解

c++代码

cpp 复制代码
class Solution {
public:
    int minFlips(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        
        auto flip = [&](int rows, int cols, bool horizontal) -> int {
            int cnt = 0;
            for (int i = 0; i < rows; ++i) {
                int l = 0, r = cols - 1;
                while (l < r) {
                    if ((horizontal && grid[i][l++] != grid[i][r--]) ||
                        (!horizontal && grid[l++][i] != grid[r--][i])) {
                        ++cnt;
                    }
                }
            }
            return cnt;
        };
        
        return min(flip(m, n, true), flip(n, m, false));
    }
};

详解

获取网格的维度

bash 复制代码
        int m = grid.size(), n = grid[0].size();
  • m 表示网格的行数。
  • n 表示网格的列数。

定义翻转操作的 lambda 函数

bash 复制代码
        auto flip = [&](int rows, int cols, bool horizontal) -> int {
            int cnt = 0;
            for (int i = 0; i < rows; ++i) {
                int l = 0, r = cols - 1;
                while (l < r) {
                    if ((horizontal && grid[i][l++] != grid[i][r--]) ||
                        (!horizontal && grid[l++][i] != grid[r--][i])) {
                        ++cnt;
                    }
                }
            }
            return cnt;
        };
  • flip 是一个 lambda 函数,用于计算需要多少次翻转才能使指定方向上的对称元素相等。
  • rows 和 cols 分别表示要检查的行数和列数。
  • horizontal 是一个布尔变量,指示是否进行水平翻转。
  • cnt 用于计数需要翻转的次数。
  • 外层循环遍历每一行(或每一列,取决于 horizontal)。
  • 内层循环使用两个指针 l 和 r 分别从两端向中间移动,比较对应位置的元素是否相等。如果不相等,则增加 cnt 计数器。

返回结果

bash 复制代码
        return min(flip(m, n, true), flip(n, m, false));
    }
};
  • 调用两次 flip 函数:
    • 第一次调用 flip(m, n, true) 进行水平翻转。
    • 第二次调用 flip(n, m, false) 进行垂直翻转。
  • 返回两者中较小的结果,即最少需要的翻转次数。

制作不易,您的关注与点赞是我最大的动力!

相关推荐
奋发向前wcx1 小时前
CSP-J复赛模拟赛4 王晨旭补题 2026.10.5
算法
念何架构之路4 小时前
zap采样器与性能优化内幕
算法·性能优化·哈希算法
晒太羊的猫5 小时前
hot100动态规划刷题
算法·动态规划
weixin_531094695 小时前
heap_4内存管理
java·开发语言·算法
余额瞒着我当琳5 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞5 小时前
win系统安装minio
java·数据结构·算法
青少儿编程课堂5 小时前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛
longlongzihan6 小时前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
waoooqwe6 小时前
问卷样本真实吗
大数据·数据库·算法·数据分析
苦瓜打怪兽6 小时前
leetcode 热题100(11. 盛最多水的容器)
python·算法·leetcode