每日一题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 函数,用于计算需要多少次翻转才能使指定方向上的对称元素相等。
  • rowscols 分别表示要检查的行数和列数。
  • horizontal 是一个布尔变量,指示是否进行水平翻转。
  • cnt 用于计数需要翻转的次数。
  • 外层循环遍历每一行(或每一列,取决于 horizontal)。
  • 内层循环使用两个指针 lr 分别从两端向中间移动,比较对应位置的元素是否相等。如果不相等,则增加 cnt 计数器。

返回结果

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

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

相关推荐
聚客AI13 小时前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v16 小时前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工17 小时前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农19 小时前
【React用到的一些算法】游标和栈
算法·react.js
博笙困了19 小时前
AcWing学习——双指针算法
c++·算法
moonlifesudo20 小时前
322:零钱兑换(三种方法)
算法
NAGNIP2 天前
大模型框架性能优化策略:延迟、吞吐量与成本权衡
算法
美团技术团队2 天前
LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
人工智能·算法
Fanxt_Ja2 天前
【LeetCode】算法详解#15 ---环形链表II
数据结构·算法·leetcode·链表
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法