2023-03-26:给定一个二维数组matrix, 每个格子都是正数,每个格子都和上、下、左、右相邻。 你可以从任何一个格子出发,走向相邻的格子, 把沿途的数字乘起来,希望得到的最终数字中,结尾的0
2023-03-26:给定一个二维数组matrix,
每个格子都是正数,每个格子都和上、下、左、右相邻。
你可以从任何一个格子出发,走向相邻的格子,
把沿途的数字乘起来,希望得到的最终数字中,结尾的0最多,
走的过程中,向左走或者向右走的拐点,最多只能有一次。
返回结尾最多的0,能是多少。
1 <= 行、列 <= 400。
答案2023-03-26:
解题思路
本题需要求出从任意位置出发,最多能有多少个结尾0。为了方便计算,可以先将矩阵中每个数分解成2和5的因子,然后通过前缀和预处理出每个位置上、左方向的2和5的因子数量之和,以便快速计算6个方向上的因子数量之和。接着遍历每个位置,分别计算6个方向上的因子数量之和,并取其中的最小值,最后返回所有最小值中的最大值即可。
具体来说,对于一个位置(i,j),可以计算它的左、右、上、下4个方向的2和5的因子数量之和,以及两个斜方向的2和5的因子数量之和共6个值。然后取这6个值中的最小值,就是从该位置出发,在该方向上能够得到的最多结尾0的数量。遍历所有位置,取最大值即可。
需要注意的是,由于只能有一次向左或向右的拐点,因此在计算左和右方向上的因子数量之和时,需要分别计算到该行左边界和右边界的因子数量之和,然后再通过减法计算出中间部分的因子数量之和。
时间复杂度
本算法需要对矩阵中每个数进行分解质因数,时间复杂度为O(n ^ 2log(max(matrix)));两层循环分别对n和m进行遍历,时间复杂度为O(nm);因此总时间复杂度为O(n^2log(max(matrix))+nm)。
空间复杂度
本算法需要维护4个二维数组,每个数组的大小均为n×m,因此空间复杂度为O(nm)。
rust代码
fn most_trailing_zeros(matrix: &Vec<Vec<i32>>) -> i32 {
let n = matrix.len(); // 矩阵行数
let m = matrix[0].len(); // 矩阵列数
// f2[i][j] : matrix[i][j]自己有几个2的因子
let mut f2 = vec![vec![0; m]; n];
// f5[i][j] : matrix[i][j]自己有几个5的因子
let mut f5 = vec![vec![0; m]; n];
// 预处理每个位置的2和5的因子数量
for i in 0..n {
for j in 0..m {
f2[i][j] = factors(matrix[i][j], 2);
f5[i][j] = factors(matrix[i][j], 5);
}
}
// 计算每个位置上、左方向的2和5的因子数量之和
let mut left_f2 = vec![vec![0; m]; n];
let mut left_f5 = vec![vec![0; m]; n];
let mut up_f2 = vec![vec![0; m]; n];
let mut up_f5 = vec![vec![0; m]; n];
for i in 0..n {
for j in 0..m {
left_f2[i][j] = f2[i][j] + if j > 0 { left_f2[i][j - 1] } else { 0 };
left_f5[i][j] = f5[i][j] + if j > 0 { left_f5[i][j - 1] } else { 0 };
up_f2[i][j] = f2[i][j] + if i > 0 { up_f2[i - 1][j] } else { 0 };
up_f5[i][j] = f5[i][j] + if i > 0 { up_f5[i - 1][j] } else { 0 };
}
}
let mut ans = 0;
for i in 0..n {
for j in 0..m {
// 来到(i,j),计算6个方向上的因子数量之和
let l2 = if j == 0 { 0 } else { left_f2[i][j - 1] }; // 左边的2因子数量之和
let l5 = if j == 0 { 0 } else { left_f5[i][j - 1] }; // 左边的5因子数量之和
let r2 = left_f2[i][m - 1] - left_f2[i][j]; // 右边的2因子数量之和
let r5 = left_f5[i][m - 1] - left_f5[i][j]; // 右边的5因子数量之和
let u2 = if i == 0 { 0 } else { up_f2[i - 1][j] }; // 上面的2因子数量之和
let u5 = if i == 0 { 0 } else { up_f5[i - 1][j] }; // 上面的5因子数量之和
let d2 = up_f2[n - 1][j] - up_f2[i][j]; // 下面的2因子数量之和
let d5 = up_f5[n - 1][j] - up_f5[i][j]; // 下面的5因子数量之和
// 计算6个方向上因子数量之和最小的值
let p1 = std::cmp::min(l2 + u2 + f2[i][j], l5 + u5 + f5[i][j]);
let p2 = std::cmp::min(l2 + r2 + f2[i][j], l5 + r5 + f5[i][j]);
let p3 = std::cmp::min(l2 + d2 + f2[i][j], l5 + d5 + f5[i][j]);
let p4 = std::cmp::min(u2 + r2 + f2[i][j], u5 + r5 + f5[i][j]);
let p5 = std::cmp::min(u2 + d2 + f2[i][j], u5 + d5 + f5[i][j]);
let p6 = std::cmp::min(r2 + d2 + f2[i][j], r5 + d5 + f5[i][j]);
// 取6个方向上的最小值中的最大值作为答案
ans = std::cmp::max(
ans,
std::cmp::max(
std::cmp::max(p1, p2),
std::cmp::max(std::cmp::max(p3, p4), std::cmp::max(p5, p6)),
),
);
}
}
ans
}
// 计算num有几个f的因子
fn factors(num: i32, f: i32) -> i32 {
let mut ans = 0;
let mut num = num;
while num % f == 0 {
ans += 1;
num /= f;
}
ans
}
fn main() {
let matrix1 = vec![
vec![5, 8, 3, 1],
vec![4, 15, 12, 1],
vec![6, 7, 10, 1],
vec![9, 1, 2, 1],
];
println!("{}", most_trailing_zeros(&matrix1)); // 输出:2
let matrix2 = vec![
vec![7500, 10, 11, 12],
vec![6250, 13, 14, 15],
vec![134, 17, 16, 1],
vec![5500, 2093, 5120, 238],
];
println!("{}", most_trailing_zeros(&matrix2)); // 输出:13
}
运行结果

2023-03-26:给定一个二维数组matrix, 每个格子都是正数,每个格子都和上、下、左、右相邻。 你可以从任何一个格子出发,走向相邻的格子, 把沿途的数字乘起来,希望得到的最终数字中,结尾的0的更多相关文章
- ytu 1050:写一个函数,使给定的一个二维数组(3×3)转置,即行列互换(水题)
1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 154 Solved: 112[ ...
- [CareerCup] 13.10 Allocate a 2D Array 分配一个二维数组
13.10 Write a function in C called my2DAlloc which allocates a two-dimensional array. Minimize the n ...
- new一个二维数组
.定义一个二维数组 char **array1 array1 = new char *[x]; for(i=0;i<x;++i) array1[i] = new char[y]; ...用的时候 ...
- c语言题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小。也可能没有鞍点
//题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小.也可能没有鞍点. // #include "stdio.h" #include <stdli ...
- php中向前台js中传送一个二维数组
在php中向前台js中传送一个二维数组,并在前台js接收获取其中值的全过程方法: (1),方法说明:现在后台将数组发送到前台 echo json_encode($result); 然后再在js页面中的 ...
- JAVA生成一个二维数组,使中间元素不与相邻的9个元素相等,并限制每一个元素的个数
JAVA生成一个二维数组,使中间元素不与相邻的9个元素相等,并限制每一个元素的个数 示例如下 至少需要九个元素:"A","B","C",&q ...
- 如何用一个for循环打印出一个二维数组
思路分析: 二维数组在内存中默认是按照行存储的,比如一个二维数组{{1,2,3,},{4,5,6}},它在内存中存储的顺序就是1.2.3.4.5.6,也就是说,对于这6个数组元素,按照从0到5给它们编 ...
- C语言程序,找出一个二维数组的鞍点。
什么是鞍点????? 鞍点就是在一个二维数组中,某一个数在该行中最大,然而其在该列中又是最小的数,这样的数称为鞍点. 昨天突然在书上看到这样的一道题,就自己尝试着写了一个找出一个二维数组中的鞍点. 好 ...
- <转载>c++中new一个二维数组
原文连接 在c++中定义一个二维数组时有多种方式,下面是几种定义方式的说明:其中dataType 表示数据类型,如int byte long... 1.dataType (*num)[n] = n ...
- C#编写程序,找一找一个二维数组中的鞍点
编写程序,找一找一个二维数组中的鞍点(即该位置上的元素值在行中最大,在该列上最小.有可能数组没有鞍点).要求: 1.二维数组的大小.数组元素的值在运行时输入: 2.程序有友好的提示信息. 代码: us ...
随机推荐
- Unity检测鼠标是否与UI交互
在Unity项目中,假设在鼠标按键时会触发游戏内的操作,但是在鼠标与UI进行交互时我们希望停止游戏中的操作,这是需要使用EventSystem中的方法来检测鼠标是否正在与UI交互 private bo ...
- mysql 存储国过程实现竖表变横表(将行数据值变为字段)
示例: 表结构如下: CREATE TABLE `pressure` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `presurena ...
- pytorch之科学计算
一.简介 torch作为深度学习的主流框架,其根本在于1.具有强大的GPU加速的张量计算功能.2.包含自动求导系统的深度神经网络.自动求导功能由torch.Autograd模块实现,而科学计算部分则直 ...
- Python实现方便的读入数字
众所周知,python只能读字符串,你如果要读整数只能读一个字符串,split成列表,再用int或者float转换. 比如这样 s=input().split() a,b=map(int,s) #或者 ...
- BL808:【M1s DOCK开发板】与LVGL 使用体验
前言 念春时已夏,恋冬雪已融. 总是感叹时光匆匆,便努力在在平凡中挣扎,在平庸中努力,在平淡中积累.奈何时代飞速发展,时间又被工作占用,外加生活中的诱惑又太多了,很多想学.想做.想超越的事,都被抛之一 ...
- Linux & 标准C语言学习 <DAY9_2>
一.进程映像 程序:存储在磁盘上的可执行文件(二进制文件.脚本文件) 进程:正在系统中运行的程序 进程映像:进程的内存分布情况 text(代码段): ...
- java选择结构-if
java选择结构-if if单选泽结构 if双选择结构 if多选择结构 if嵌套结构 package charpter2; import com.sun.xml.internal.ws.address ...
- VirtualBox下宿主机和Linux虚拟机共享文件配置方法
VirtualBox版本-5.2.8 Linux版本-Ubuntu16.04 2020.03.31 一.首先在宿主机上新建一个文件夹,这里命名为共享文件夹(如果读者自行命名记得后文全部替换),存放了一 ...
- 【Visual Leak Detector】QT 中 VLD 输出解析(一)
说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记. 目录 说明 1. 使用方式 2. 无内存泄漏时的输出报告 1. 使用方式 在 QT 中使用 VLD 的方法可以查看另外几篇博客: [Vi ...
- 设计模式(三十一)----综合应用-自定义Spring框架-自定义Spring IOC-定义解析器、IOC容器相关类
3 定义解析器相关类 3.1 BeanDefinitionReader接口 BeanDefinitionReader是用来解析配置文件并在注册表中注册bean的信息.定义了两个规范: 获取注册表的功能 ...