美团校招机试 - 小美的平衡矩阵(20240309-T1)

题目来源

美团校招笔试真题_小美的平衡矩阵

题目描述

小美拿到了一个 n * n  的矩阵,其中每个元素是 0 或者 1。

小美认为一个矩形区域是完美的,当且仅当该区域内 0 的数量恰好等于 1 的数量。

现在,小美希望你回答有多少个 i * i 的完美矩形区域。你需要回答 1 ≤ i ≤ n 的所有答案。

输入描述

第一行输入一个正整数 n,代表矩阵大小。

  • 1 ≤ n ≤ 200

接下来的 n 行,每行输入一个长度为 n 的 01 串,用来表示矩阵。

输出描述

输出 n 行,第 i 行输出的 i * i 的完美矩形区域的数量。

用例

输入4
1010
0101
1100
0011
输出0
7
0
1
说明

题目解析

本题需要我们求解 i * i 的完美矩形区域的数量,i 取值 1~n.

完美矩形区域:当且仅当该区域内 0 的数量恰好等于 1 的数量

比如下图中黄色部分是一个 2x2 的矩形区域,其中01数量相等,因此是一个完美矩形区域

因此,本题的关键其实是,求解输入矩阵中,任意 i * i 正方形区域中 '1' 的数量oneCount,如果满足: oneCount * 2 == i * i,则对应正方形区域是完美的。

那么,如何求解输入矩阵中,任意正方形区域中 '1' 的数量呢?

我们可以基于“二维数组前缀和”的知识来求解。

假设 dp[i][j] 表示输入矩阵中以 (0,0)为左上角点,(i,j)为右下角点的矩形中 '1' 的数量。

比如上图中,dp[1][1] = 2,即以(0,0)为左上角点,(1,1)为左下角点的矩形中 '1' 的数量为 2。

下图中红色区域1的数量存在关系如下:

其中橙色区域 是 绿色和蓝色区域的重叠区域,为了避免重复计算,所以要减去。

即存在状态转移方程如下:

dp[i][j] = dp[i][j-1]dp[i-1][j] - dp[i-1][j-1] + (matrix[i][j] == '1' ? 1 : 0)

上面状态转移方程求解i=0, j=0的右下角位置矩形时,会发生越界异常,

因此我们定义dp二维数组时,需要将dp矩阵的行数、列数都定义为n+1。dp矩阵的第一行和第一列初始为0。

之后,我们就可以遍历dp中所有正方形,然后基于dp来求解正方形中1的数量。比如下图中:

我们要求解:边长为 i=2,右下角位置 (r=3, c=2) 的正方形中 '1' 的数量,则有公式如下:

dp[r][c] - dp[r][c - i] - dp[r - i][c] + dp[r - i][c - i]

公式可以对照下图理解: 

JS(Node)算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {const n = parseInt(await readline());const matrix = [];for (let i = 0; i < n; i++) {matrix.push(await readline());}// 二维数组前缀和// dp[i][j] 表示matrix矩阵中以 (i-1, j-1) 位置为右下角点的矩形中1的数量const dp = new Array(n + 1).fill(0).map(() => new Array(n + 1).fill(0));for (let i = 1; i <= n; i++) {for (let j = 1; j <= n; j++) {// 此处公式请看图示说明dp[i][j] =parseInt(matrix[i - 1][j - 1]) +dp[i - 1][j] +dp[i][j - 1] -dp[i - 1][j - 1];}}// i 表示正方形边长for (let i = 2; i <= n; i += 2) {// i 为奇数时, 则对应 i*i 正方形面积也为奇数, 不可能平分, 所以不存在01平衡的console.log(0);// i 为偶数时let count = 0; // 记录01平衡的i*i正方形数量for (let r = i; r <= n; r++) {for (let c = i; c <= n; c++) {// 正方形中1的数量const oneCount =dp[r][c] - dp[r][c - i] - dp[r - i][c] + dp[r - i][c - i];// 如果正方形中1的数量 == 正方形面积的一半,则形成01平衡if (oneCount * 2 == i * i) {count++;}}}console.log(count);}// 如果 n 是奇数,则上面for循环会遗漏 n*n 正方形的01平衡判断if (n % 2 != 0) {console.log(0);}
})();

Java算法源码

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = Integer.parseInt(sc.nextLine());char[][] matrix = new char[n][n];for (int i = 0; i < n; i++) {matrix[i] = sc.nextLine().toCharArray();}// 二维数组前缀和// dp[i][j] 表示matrix矩阵中以 (i-1, j-1) 位置为右下角点的矩形中1的数量int[][] dp = new int[n + 1][n + 1];for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {// 此处公式请看图示说明dp[i][j] = (matrix[i - 1][j - 1] - '0') + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];}}// i 表示正方形边长for (int i = 2; i <= n; i += 2) {// i 为奇数时, 则对应 i*i 正方形面积也为奇数, 不可能平分, 所以不存在01平衡的System.out.println(0);// i 为偶数时int count = 0; // 记录01平衡的i*i正方形数量for (int r = i; r <= n; r++) {for (int c = i; c <= n; c++) {// 正方形中1的数量int oneCount = dp[r][c] - dp[r][c - i] - dp[r - i][c] + dp[r - i][c - i];// 如果正方形中1的数量 == 正方形面积的一半,则形成01平衡if (oneCount * 2 == i * i) {count++;}}}System.out.println(count);}// 如果 n 是奇数,则上面for循环会遗漏 n*n 正方形的01平衡判断if (n % 2 != 0) {System.out.println(0);}}
}

Python算法源码

# 输入获取
n = int(input())
matrix = [input() for _ in range(n)]# 核心代码
if __name__ == '__main__':# 二维数组前缀和# dp[i][j] 表示matrix矩阵中以 (i-1, j-1) 位置为右下角点的矩形中1的数量dp = [[0] * (n + 1) for _ in range(n + 1)]for i in range(1, n + 1):for j in range(1, n + 1):# 此处公式请看图示说明dp[i][j] = int(matrix[i - 1][j - 1]) + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1]# i 表示正方形边长for i in range(2, n + 1, 2):# i 为奇数时, 则对应 i*i 正方形面积也为奇数, 不可能平分, 所以不存在01平衡的print(0)# i 为偶数时count = 0  # 记录01平衡的i*i正方形数量for r in range(i, n + 1):for c in range(i, n + 1):# 正方形中1的数量oneCount = dp[r][c] - dp[r][c - i] - dp[r - i][c] + dp[r - i][c - i]# 如果正方形中1的数量 == 正方形面积的一半,则形成01平衡if oneCount * 2 == i * i:count += 1print(count)# 如果 n 是奇数,则上面for循环会遗漏 n*n 正方形的01平衡判断if n % 2 != 0:print(0)

C算法源码

#include <stdio.h>#define MAX_SIZE 201int main() {int n;scanf("%d", &n);char matrix[MAX_SIZE][MAX_SIZE] = {'\0'};for (int i = 0; i < n; i++) {scanf("%s", matrix[i]);}// 二维数组前缀和// dp[i][j] 表示matrix矩阵中以 (i-1, j-1) 位置为右下角点的矩形中1的数量int dp[MAX_SIZE][MAX_SIZE] = {0};for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {// 此处公式请看图示说明dp[i][j] = (matrix[i - 1][j - 1] - '0') + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];}}// i 表示正方形边长for (int i = 2; i <= n; i += 2) {// i 为奇数时, 则对应 i*i 正方形面积也为奇数, 不可能平分, 所以不存在01平衡的puts("0");// i 为偶数时int count = 0; // 记录01平衡的i*i正方形数量for (int r = i; r <= n; r++) {for (int c = i; c <= n; c++) {// 正方形中1的数量int oneCount = dp[r][c] - dp[r][c - i] - dp[r - i][c] + dp[r - i][c - i];// 如果正方形中1的数量 == 正方形面积的一半,则形成01平衡if (oneCount * 2 == i * i) {count++;}}}printf("%d\n", count);}// 如果 n 是奇数,则上面for循环会遗漏 n*n 正方形的01平衡判断if (n % 2 != 0) {puts("0");}return 0;
}

C++算法源码

#include <bits/stdc++.h>
using namespace std;int main() {int n;cin >> n;vector<string> matrix(n);for (int i = 0; i < n; i++) {cin >> matrix[i];}// 二维数组前缀和// dp[i][j] 表示matrix矩阵中以 (i-1, j-1) 位置为右下角点的矩形中1的数量vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {// 此处公式请看图示说明dp[i][j] = (matrix[i - 1][j - 1] - '0') + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];}}// i 表示正方形边长for (int i = 2; i <= n; i += 2) {// i 为奇数时, 则对应 i*i 正方形面积也为奇数, 不可能平分, 所以不存在01平衡的cout << 0 << endl;// i 为偶数时int count = 0; // 记录01平衡的i*i正方形数量for (int r = i; r <= n; r++) {for (int c = i; c <= n; c++) {// 正方形中1的数量int oneCount = dp[r][c] - dp[r][c - i] - dp[r - i][c] + dp[r - i][c - i];// 如果正方形中1的数量 == 正方形面积的一半,则形成01平衡if (oneCount * 2 == i * i) {count++;}}}cout << count << endl;}// 如果 n 是奇数,则上面for循环会遗漏 n*n 正方形的01平衡判断if (n % 2 != 0) {cout << 0 << endl;}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis哨兵模式(Redis Sentinel)

哨兵模式的背景 当主服务器宕机后&#xff0c;需要手动把一台从服务器切换为主服务器&#xff0c;这就需要人工干预&#xff0c;费事费力&#xff0c;还会造成一段时间内服务不可用。这不是一种推荐的方式。 为了解决单点故障和提高系统的可用性&#xff0c;需要一种自动化的监…

固态硬盘与机械硬盘之间的区别

固态硬盘与机械硬盘之间有哪些方面的区别呢&#xff1f; 固态硬盘和机械硬盘在容量方面就有着一定的区别&#xff0c;固态硬盘主要是半导体存储&#xff0c;通常是直接存储在闪存颗粒当中&#xff0c;因为每个闪存颗粒的容量是有限的&#xff0c;所以固态硬盘的存储容量相对小一…

暑假本科生、研究生怎么学?来看详细的AI夏令营规划

Datawhale夏令营 发布&#xff1a;2024 AI 夏令营 学习规划 「学习内容详览」 01机器学习方向&#xff1a;2024/7/1~7/7 「Datawhale」邀请想入门人工智能领域并实践机器学习算法的学习者和我们一起来学习~ 详细学习规划如下&#xff1a; 02大模型技术方向&#xff1a;2024/7…

基于springboot、vue汽车租赁系统

设计技术&#xff1a; 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatisvue工具&#xff1a;IDEA、Maven、Navicat 主要功能&#xff1a; 用户进入系统可以查看首页、个人中心、车辆信息管理、租赁订单列表管理、还车记录管理等操作 管理…

SAP-创建预留和采购申请

METHOD zyc_ii_si_data_dump_in~si_data_dump_in. "反馈 DATA: output_hd TYPE zmmi005_dt_mesg_hd, output_body TYPE zun_dt_un_resp_msgbd_tab, output_line TYPE zun_dt_un_resp_msgbd. DATA: r_obj TYPE REF TO zun_co_si_un_resp_out, out TYPE zun_mt_un_resp. * T…

串级PID控制算原理及法详解

文章目录 1. PID 2. 串级PID 3. 串级PID的物理量 4. C语言实现单极PID 5. C语言实现串极PID 6. 模拟仿真 1. PID PID是应用最广泛的闭环控制方法之一&#xff0c;是一种常用的反馈控制方法&#xff0c;对于每个PID控制器由三个部分组成&#xff1a;比例控制&#xff08;…

自然语言处理——英文文本预处理

高质量数据的重要性 数据的质量直接影响模型的性能和准确性。高质量的数据可以显著提升模型的学习效果&#xff0c;帮助模型更准确地识别模式、进行预测和决策。具体原因包括以下几点&#xff1a; 噪音减少&#xff1a;高质量的数据经过清理&#xff0c;减少了无关或错误信息…

Wp-scan一键扫描wordpress网页(KALI工具系列三十)

目录 1、KALI LINUX 简介 2、Wp-scan工具简介 3、信息收集 3.1 目标IP&#xff08;服务器) 3.2kali的IP 4、操作实例 4.1 基本扫描 4.2 扫描已知漏洞 4.3 扫描目标主题 4.4 列出用户 4.5 输出扫描文件 4.6 输出详细结果 5、总结 1、KALI LINUX 简介 Kali Linux 是一…

《梦醒蝶飞:释放Excel函数与公式的力量》6.1 DATE函数

6.1 DATE函数 第一节&#xff1a;DATE函数 1&#xff09;DATE函数概述 DATE函数是Excel中的一个内置函数&#xff0c;用于根据指定的年、月、日返回对应的日期序列号。这个函数非常有用&#xff0c;尤其是在处理日期数据时&#xff0c;它可以帮助你构建特定的日期&#xff0…

pycharm工具回退键调出

pycharm工具调出回退键。 View->Appearance->Toolbar,即可调出 调不出的可以使用快捷键&#xff1a;ctrlalt向左箭头 但是这个快捷键容易和电脑屏幕旋转冲突。可将电脑的快捷键关掉&#xff0c;即可。 ctrlalt向上箭头&#xff1a;将屏幕旋转到正常&#xff08;横向&am…

【面试干货】final、finalize 和 finally 的区别

【面试干货】final、finalize 和 finally 的区别 1、final1.1 修饰类1.2 修饰方法1.3 修饰变量 2、finally3、finalize4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java编程语言中&#xff0c;final、finalize和finally都是关键…

汽车免拆诊断案例 | 2016 款吉利帝豪EV车无法加速

故障现象 一辆2016款吉利帝豪EV车&#xff0c;累计行驶里程约为28.4万km&#xff0c;车主反映车辆无法加速。 故障诊断 接车后路试&#xff0c;行驶约1 km&#xff0c;踩下加速踏板&#xff0c;无法加速&#xff0c;车速为20 km/h左右&#xff0c;同时组合仪表上的电机及控制…

设备驱动框架之LED

文章目录 前言一、什么是驱动框架二、使用步骤1.注册LED设备2.卸载LED设备3.内核中申请内存4.container_of5.platform_get_drvdata 和 platform_set_drvdata6.module_platform_driver 三、驱动示例总结 前言 为了尽量降低驱动开发者难度以及接口标准化&#xff0c;就出现了设备…

面试-Java线程池

1.利用Excutors创建不同的线程池满足不同场景的需求 分析&#xff1a; 如果并发的请求的数量非常多&#xff0c;但每个线程执行的时间非常短&#xff0c;这样就会频繁的创建和销毁线程。如此一来&#xff0c;会大大降低系统的效率。 可能出现&#xff0c;服务器在为每个线程创建…

Docker创建容器时提示 [Warning] IPv4 forwarding is disabled. Networking will not work.

解决办法 1. 在docker的宿主机中更改以下文件&#xff1a; [rootlocalhost ~]# vi /usr/lib/sysctl.d/00-system.conf2. 添加如下代码&#xff1a; net.ipv4.ip_forward13. 重启network服务&#xff1a; systemctl restart network

Lua 垃圾回收

Lua 垃圾回收 Lua 是一种轻量级的编程语言&#xff0c;广泛用于游戏开发、脚本编写和其他应用程序。Lua 的设计哲学是简单和高效&#xff0c;这同样体现在它的内存管理机制中。在 Lua 中&#xff0c;垃圾回收&#xff08;Garbage Collection&#xff0c;简称 GC&#xff09;是…

利用powershell开展网络钓鱼

要确保人们打开我们的恶意文件并执行它们&#xff0c;我们只需让微软努力工作多年来赢得人们的信任&#xff0c;然后将一些危险的宏插入到幻灯片中。 本博文将介绍如何通过屏幕顶部的一个友好的警告提示&#xff0c;在用户启用宏后立即运行您的宏。 首先&#xff0c;我们需要打…

【面向对象】复习(四)

const构不构成重载 C 加const能不能构成重载的几种情况_多个const修饰可以重载吗-CSDN博客

如何在Java中实现并发编程,包括锁机制、线程池等。

在Java中实现并发编程有很多种方式&#xff0c;包括使用锁机制、线程池等。以下是一些基本的步骤和代码示例&#xff1a; 1. **锁机制**&#xff1a;Java提供了多种锁机制&#xff0c;包括ReentrantLock&#xff0c;synchronized关键字等。ReentrantLock是一个可重入的锁&…

[分布式网络通讯框架]----MprpcApplication实现

在之前我们提到了很多回MprpcApplication类&#xff0c;这是一个mprpc框架的初始化类。 在此之前&#xff0c;先来看看MprpcConfig 类 MprpcConfig 类 重要成员变量 std::unordered_map<std::string,std::string> m_configMap;存放配置信息键值对。 本项目配置信息 …