leetcode 2245. 转角路径的乘积中最多能有几个尾随零

该博客介绍了如何解决一个算法问题,即在给定的二维矩阵中找到一条转角路径,使得路径上的数字乘积拥有最多的尾随零。问题通过前缀和优化来统计每个单元格在不同方向上2和5的因子,然后枚举每个点作为拐点,计算四种可能路径的尾随零数量,取最大值。示例展示了如何在给定的矩阵中找到这样的路径并返回尾随零的数量。
摘要由CSDN通过智能技术生成

2245. 转角路径的乘积中最多能有几个尾随零

给你一个二维整数数组 grid ,大小为 m x n,其中每个单元格都含一个正整数。

转角路径 定义为:包含至多一个弯的一组相邻单元。具体而言,路径应该完全 向水平方向 或者 向竖直方向 移动过弯(如果存在弯),而不能访问之前访问过的单元格。在过弯之后,路径应当完全朝 另一个 方向行进:如果之前是向水平方向,那么就应该变为向竖直方向;反之亦然。当然,同样不能访问之前已经访问过的单元格。

一条路径的 乘积 定义为:路径上所有值的乘积。

请你从 grid 中找出一条乘积中尾随零数目最多的转角路径,并返回该路径中尾随零的数目。

注意:

水平 移动是指向左或右移动。
竖直 移动是指向上或下移动。

示例 1:

输入:grid =
[[23,17,15,3,20],[8,1,20,27,11],[9,4,6,2,21],[40,9,1,10,6],[22,7,4,5,3]]
输出:3
解释:
左侧的图展示了一条有效的转角路径。 其乘积为 15 * 20 * 6 * 1 * 10 = 18000 ,共计 3个尾随零。 可以证明在这条转角路径的乘积中尾随零数目最多。

中间的图不是一条有效的转角路径,因为它有不止一个弯。
右侧的图也不是一条有效的转角路径,因为它需要重复访问已经访问过的单元格。

在这里插入图片描述

示例 2:

输入:grid = [[4,3,2],[7,6,1],[8,8,8]]
输出:0

解释:网格如上图所示。 不存在乘积含尾随零的转角路径。

在这里插入图片描述

提示:

m == grid.length n == grid[i].length 1 <= m, n <= 1e5
1 <= m * n <=1e5
1 <= grid[i][j] <= 1000

解析:
1,路径的开头和结尾一定为边缘结点
2,每个结点为拐点,有四种情况
3,采用前缀和记录每个点在左 上方向上2,5的个数优化
code:

class Solution {
public:
    int maxTrailingZeros(vector<vector<int>>& grid) {
        int m=grid.size();
        int n=grid[0].size();
        // 0 1 2 3 分别存储左2,上2,左5,上5
        vector<vector<vector<int>>> vec(m+1,vector<vector<int>>(n+1,vector<int>(4,0)));
        // 将0位置空出,防止越界
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                int x=grid[i-1][j-1];
                int t=0;
                int f=0;
                // 统计每个数字包含2 5因子的个数,并用前缀和记录个数
                while(x%2==0)t++,x/=2;
                while(x%5==0)f++,x/=5;
                vec[i][j][0]=vec[i][j-1][0]+t;
                vec[i][j][1]=vec[i-1][j][1]+t;
                vec[i][j][2]=vec[i][j-1][2]+f;
                vec[i][j][3]=vec[i-1][j][3]+f;
            }
        }
        // 枚举每个点为拐点计算四种组合的最大值
        int ans=0;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                int t=vec[i][j][0]-vec[i][j-1][0];
                int f=vec[i][j][2]-vec[i][j-1][2];
                //printf("%d %d %d %d\n",vec[i][j][0],vec[i][j][1],vec[i][j][2],vec[i][j][3]);
                ans=max(ans,min(vec[i][j][0]+vec[i][j][1]-t,vec[i][j][2]+vec[i][j][3]-f));
                //cout<<ans<<" ";
                ans=max(ans,min(vec[i][j][0]+vec[m][j][1]-vec[i][j][1],vec[i][j][2]+vec[m][j][3]-vec[i][j][3]));
                //cout<<ans<<" ";
                ans=max(ans,min(vec[i][j][1]+vec[i][n][0]-vec[i][j][0],vec[i][j][3]+vec[i][n][2]-vec[i][j][2]));
                //cout<<ans<<" ";
                ans=max(ans,min(vec[m][j][1]-vec[i][j][1]+vec[i][n][0]-vec[i][j][0]+t,
                                vec[m][j][3]-vec[i][j][3]+vec[i][n][2]-vec[i][j][2]+f));
                //cout<<ans<<"\n";
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值