LeetCode 3240.最少翻转次数使二进制矩阵回文 II:分类讨论

【LetMeFly】3240.最少翻转次数使二进制矩阵回文 II:分类讨论

力扣题目链接:https://leetcode.cn/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-ii/

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

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

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

请你返回 最少 翻转次数,使得矩阵中 所有 行和列都是 回文的 ,且矩阵中 1 的数目可以被 4 整除 。

 

示例 1:

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

输出:3

解释:

示例 2:

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

输出:2

解释:

示例 3:

输入:grid = [[1],[1]]

输出:2

解释:

 

提示:

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

解题方法:分类讨论

step1: 先不考虑4的倍数个1,计算最小翻转次数

step2: 再考虑1的个数问题:

  • 偶数行偶数列:(1必定是4的倍数个)直接返回

  • 奇数行偶数列:看中间那一行有多少对11和多少对10/01

    • 偶数对11:(step1时可以把所有01/10变成00)直接返回

    • 奇数对11:看有无10/01:

      • 有10/01:(step1时把中间这一行的其中一对10/01变成11)直接返回
      • 无10/01:(step2必须把一对11变成00)step1结果+2后返回
  • 偶数行奇数列:和奇数行偶数列同理

  • 奇数行奇数列:要看“最中心元素”和“中间行中间列除最中间元素外的部分”两部分

    • 最中心元素:

      • 若为1:(必须变为0)step1+1
      • 若为0:step1不变
    • 中间行中间列除最中间元素外的部分:类似奇数行偶数列,统计这些元素中所有的11对和10/01对,之后同理

  • 时间复杂度 O ( n m ) O(nm) O(nm)

  • 空间复杂度 O ( 1 ) O(1) O(1)

不难发现,也可以直接判定是否存在“中间行”和“中间列”进行代码简化。

AC代码

C++ 复杂版
/*
step1: 先不考虑4的倍数个1,计算最小翻转次数step2: 再考虑1的个数问题:偶数行偶数列:(1必定是4的倍数个)直接返回
奇数行偶数列:看中间那一行有多少对11和多少对10/01+ 偶数对11:(step1时可以把所有01/10变成00)直接返回+ 奇数对11:看有无10/01:+ 有10/01:(step1时把中间这一行的其中一对10/01变成11)直接返回+ 无10/01:(step2必须把一对11变成00)step1结果+2后返回
偶数行奇数列:和奇数行偶数列同理
奇数行奇数列:要看“最中心元素”和“中间行中间列除最中间元素外的部分”两部分+ 最中心元素:+ 若为1:(必须变为0)step1+1+ 若为0:step1不变+ 中间行中间列除最中间元素外的部分:类似奇数行偶数列,统计这些元素中所有的11对和10/01对,之后同理
*/
class Solution {
public:int minFlips(vector<vector<int>>& grid) {int ans = 0;int n = grid.size(), m = grid[0].size();for (int i = 0; i < n / 2; i++) {for (int j = 0; j < m / 2; j++) {int cnt1 = grid[i][j] + grid[i][m - j - 1] + grid[n - i - 1][j] + grid[n - i - 1][m - j - 1];ans += min(cnt1, 4 - cnt1);}}if (n % 2 == 0 && m % 2 == 0) {return ans;} else if (n % 2 == 1 && m % 2 == 0) {int cnt11 = 0, cnt0110 = 0;for (int j = 0; j < m / 2; j++) {if (grid[n / 2][j] == grid[n / 2][m - j - 1]) {if (grid[n / 2][j] == 1) {cnt11++;}} else {cnt0110++;}}ans += cnt0110;if (cnt11 % 2 == 0 || cnt0110 > 0) {return ans;} else {return ans + 2;}} else if (n % 2 == 0 && m % 2 == 1) {int cnt11 = 0, cnt0110 = 0;for (int i = 0; i < n / 2; i++) {if (grid[i][m / 2] == grid[n - i - 1][m / 2]) {if (grid[i][m / 2] == 1) {cnt11++;}} else {cnt0110++;}}ans += cnt0110;if (cnt11 % 2 == 0 || cnt0110 > 0) {return ans;} else {return ans + 2;}} else {if (grid[n / 2][m / 2]) {ans++;}int cnt11 = 0, cnt0110 = 0;for (int j = 0; j < m / 2; j++) {if (grid[n / 2][j] == grid[n / 2][m - j - 1]) {if (grid[n / 2][j] == 1) {cnt11++;}} else {cnt0110++;}}for (int i = 0; i < n / 2; i++) {if (grid[i][m / 2] == grid[n - i - 1][m / 2]) {if (grid[i][m / 2] == 1) {cnt11++;}} else {cnt0110++;}}ans += cnt0110;if (cnt11 % 2 == 0 || cnt0110 > 0) {return ans;} else {return ans + 2;}}}
};
C++ 简化版
class Solution {
public:int minFlips(vector<vector<int>>& grid) {int ans = 0;int n = grid.size(), m = grid[0].size();for (int i = 0; i < n / 2; i++) {for (int j = 0; j < m / 2; j++) {int cnt1 = grid[i][j] + grid[i][m - j - 1] + grid[n - i - 1][j] + grid[n - i - 1][m - j - 1];ans += min(cnt1, 4 - cnt1);}}if (n % 2 && m % 2) {ans += grid[n / 2][m / 2];}int cnt11 = 0, cnt0110 = 0;if (n % 2 == 1) {for (int j = 0; j < m / 2; j++) {if (grid[n / 2][j] == grid[n / 2][m - j - 1]) {if (grid[n / 2][j] == 1) {cnt11++;}} else {cnt0110++;}}}if (m % 2 == 1) {for (int i = 0; i < n / 2; i++) {if (grid[i][m / 2] == grid[n - i - 1][m / 2]) {if (grid[i][m / 2] == 1) {cnt11++;}} else {cnt0110++;}}}ans += cnt0110;if (cnt11 % 2 == 0 || cnt0110 > 0) {return ans;} else {return ans + 2;}return ans;}
};
Python
from typing import Listclass Solution:def minFlips(self, grid: List[List[int]]) -> int:ans = 0n, m = len(grid), len(grid[0])for i in range(n // 2):for j in range(m // 2):cnt1 = grid[i][j] + grid[i][m - j - 1] + grid[n - i - 1][j] + grid[n - i - 1][m - j - 1]ans += min(cnt1, 4 - cnt1)if n % 2 and m % 2:ans += grid[n // 2][m // 2]cnt11, cnt1001 = 0, 0if n % 2:for j in range(m // 2):if grid[n // 2][j] == grid[n // 2][m - j - 1]:if grid[n // 2][j] == 1:cnt11 += 1else:cnt1001 += 1if m % 2:for i in range(n // 2):if grid[i][m // 2] == grid[n - i - 1][m // 2]:if grid[i][m // 2] == 1:cnt11 += 1else:cnt1001 += 1ans += cnt1001if cnt11 % 2 and not cnt1001:ans += 2return ans
Java
class Solution {public int minFlips(int[][] grid) {int ans = 0;int n = grid.length, m = grid[0].length;for (int i = 0; i < n / 2; i++) {for (int j = 0; j < m / 2; j++) {int cnt1 = grid[i][j] + grid[i][m - j - 1] + grid[n - i - 1][j] + grid[n - i - 1][m - j - 1];ans += Math.min(cnt1, 4 - cnt1);}}if (n % 2 == 1 && m % 2 == 1) {ans += grid[n / 2][m / 2];}int cnt11 = 0, cnt0110 = 0;if (n % 2 == 1) {for (int j = 0; j < m / 2; j++) {if (grid[n / 2][j] == grid[n / 2][m - j - 1]) {if (grid[n / 2][j] == 1) {cnt11++;}} else {cnt0110++;}}}if (m % 2 == 1) {for (int i = 0; i < n / 2; i++) {if (grid[i][m / 2] == grid[n - i - 1][m / 2]) {if (grid[i][m / 2] == 1) {cnt11++;}} else {cnt0110++;}}}ans += cnt0110;if (cnt11 % 2 == 1 && cnt0110 == 0) {ans += 2;}return ans;}
}
Go
package mainfunc minFlips(grid [][]int) (ans int) {n, m := len(grid), len(grid[0])for i := 0; i < n / 2; i++ {for j := 0; j < m / 2; j++ {cnt1 := grid[i][j] + grid[i][m - j - 1] + grid[n - i - 1][j] + grid[n - i - 1][m - j - 1]ans += min(cnt1, 4 - cnt1)}}if n % 2 == 1 && m % 2 == 1 {ans += grid[n / 2][m / 2]}cnt11, cnt1001 := 0, 0if n % 2 == 1 {for j := 0; j < m / 2; j++ {if grid[n / 2][j] == grid[n / 2][m - j - 1] {if grid[n / 2][j] == 1 {cnt11++}} else {cnt1001++}}}if m % 2 == 1 {for i := 0; i < n / 2; i++ {if grid[i][m / 2] == grid[n - i - 1][m / 2] {if (grid[i][m / 2] == 1) {cnt11++}} else {cnt1001++}}}ans += cnt1001if cnt11 % 2 == 1 && cnt1001 == 0 {ans +=2}return
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/143816332

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/17352.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

在kile 5中一个新工程的创建

这两天博主学习到了在kile5中创建一个工程&#xff0c;当然博主不会忘了小伙伴们的&#xff0c;这就和你们分享。 本次创建以STM32F103C8为例 创建过程&#xff1a; 1首先创建文件 名字随意&#xff0c;但也不要太随意&#xff0c;因为是外国软件&#xff0c;所以多少对中文…

深度学习工具和框架详细指南:PyTorch、TensorFlow、Keras

引言 在深度学习的世界中&#xff0c;PyTorch、TensorFlow和Keras是最受欢迎的工具和框架&#xff0c;它们为研究者和开发者提供了强大且易于使用的接口。在本文中&#xff0c;我们将深入探索这三个框架&#xff0c;涵盖如何用它们实现经典深度学习模型&#xff0c;并通过代码…

2024-11-16 特殊矩阵的压缩存储

一、数组的存储结构 1.一维数组&#xff1a;各元素大小相同&#xff0c;且物理上连续存放。a[i]起始地址i*siezof(数组元素大小) 2.二维数组&#xff1a;b[j][j]起始地址&#xff08;i*Nj&#xff09;*sizeof(数组元素大小) 二、特殊矩阵 1.普通矩阵的存储&#xff1a;使用…

ISCTF2024

ezlogin 源码审计 先审源码,纯js题 const express require(express); const app express(); const bodyParser require(body-parser); var cookieParser require(cookie-parser); var serialize require(node-serialize); app.use(bodyParser.urlencoded({ e…

leetcode226:反转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]示例 3&#x…

Excel365和WPS中提取字符串的五种方法

一、问题的提出 如何在WPS或者Excel365中提取A列指定的字符串&#xff0c;从"面"开始一直到".pdf"? 问题的提出 二、问题的分析 我们可以采用多种方法解决这个问题&#xff0c;由于A列到B列的提取是非常有规律的&#xff0c;因此我们可以采用如下几种方…

下载jakarta-taglibs-standard-current.zip

官网&#xff1a;https://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ 下载版本&#xff1a;

Qt信号和槽

信号和槽的概念 在Linux中我们也学过信号 Signal&#xff0c;这是进程间通信的一种方式&#xff0c;这里大致分为三个要素&#xff1a; 信号源&#xff1a;谁发送的信号&#xff08;用户进程&#xff0c;系统内核&#xff0c;终端或者作业控制&#xff0c;&#xff09; 信号的类…

MATLAB绘图

一、实验内容和步骤 MATLAB的图形功能非常强大&#xff0c;可以对二维、三维数据用图形表现&#xff0c;并可以对图形的线形、曲面、视觉、色彩和光线等进行处理。 1、绘制二维曲线 绘制如下图所示的图形&#xff0c;把图形窗口分割为2列2行&#xff0c;在窗口1中绘制一条正弦…

H3C NX30Pro刷机教程-2024-11-16

H3C NX30Pro刷机教程-2024-11-16 ref: http://www.ttcoder.cn/index.php/2024/11/03/h3c-nx30pro亲测无需分区备份 路由器-新机初始化设置路由器登录密码telnet进入路由器后台 刷机上传uboot到路由器后台在Windows环境下解压后的软件包中打开 tftpd64.exe在NX30Pro环境下通过以…

boost之property

简介 property在boost.graph中有使用&#xff0c;用于表示点属性或者边属性 结构 #mermaid-svg-56YI0wFLPH0wixrJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-56YI0wFLPH0wixrJ .error-icon{fill:#552222;}#me…

[C++] 智能指针

文章目录 智能指针的使用原因及场景分析为什么需要智能指针&#xff1f;异常抛出导致的资源泄漏问题分析 智能指针与RAIIC常用智能指针 使用智能指针优化代码优化后的代码优化点分析 析构函数中的异常问题解决方法 RAII 和智能指针的设计思路详解什么是 RAII&#xff1f;RAII 的…

Android数据存储

前言 在前面&#xff0c;我们已经学了控件和布局&#xff0c;那么我们在存储数据的时候&#xff0c;并不能持久化的存储&#xff0c;所以我们需要来学习一些如何持久化存储数据的方式. 数据存储方式 文件存储&#xff1a;在android中提供了openFileInput()方法和openFileOut…

Java基础——多线程

1. 线程 是一个程序内部的一条执行流程程序中如果只有一条执行流程&#xff0c;那这个程序就是单线程的程序 2. 多线程 指从软硬件上实现的多条执行流程的技术&#xff08;多条线程由CPU负责调度执行&#xff09; 2.1. 如何创建多条线程 Java通过java.lang.Thread类的对象…

【网络】网络层——IP协议

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解在网络层下的IP协议。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;网络…

获取当前程序运行时的栈大小[C语言]

废话前言 一晃已经毕业了4年&#xff0c;也在某个时间点&#xff0c;从面试者转变成了面试官。 进行第一次面试的时候&#xff0c;我好像比候选人还慌张&#xff0c;压根不知道问什么&#xff0c;好在是同行业&#xff0c;看着简历问了一些协议内容以及模块设计思路&#xff0…

人工智能之数学基础:数学在人工智能领域中的地位

人工智能&#xff08;AI&#xff09;是一种新兴的技术&#xff0c;它的目标是构建能够像人类一样思考、学习、推理和解决问题的智能机器。AI已经成为了许多行业的重要组成部分&#xff0c;包括医疗、金融、交通、教育等。而数学则是AI领域中不可或缺的基础学科。本文将阐述数学…

UE5 第一人称射击项目学习(一)

因为工作需要&#xff0c;需要掌握ue5的操作。 选择了视频资料 UE5游戏制作教程Unreal Engine 5 C作为学习。 第一个目标是跟着视频制作出一款第一人称射击项目。 同时作为入门&#xff0c;这个项目不会涉及到C&#xff0c;而是一个纯蓝图的项目。 项目目标 这个项目将实…

图像分类之花卉识别实验验证

本实验基于37种主流的图像分类算法模型&#xff0c;对64种花卉进行识别。使用包括vgg、resnet、densenet、efficientnet、inception、mobilenet等37种图像分类模型进行实验&#xff0c;评估各种模型对花卉的识别准确度、计算量、参数量&#xff0c;对比不同模型的性能和优缺点。…

Linux基础开发工具使用

目录 1. 软件包管理器yum 1.1 概念介绍 1.2 更换镜像源&#xff08;可选&#xff09; 1.3 工具的搜索/查看/安装/卸载 1.4 优势 2. vim编辑器 2.1 vi和vim 2.2 三种常用模式和操作 2.3 配置vim 3. Linux编译器-gcc/g 4. Linux调试器-gdb 5. make和Makefile 6.…