首页 > 编程语言 >编写一个算法来计算 n 阶乘中尾随零的数量

编写一个算法来计算 n 阶乘中尾随零的数量

时间:2024-04-03 22:34:52浏览次数:19  
标签:count 25 int 代码 个数 算法 尾随 阶乘

算法:编写一个算法来计算 n 阶乘中尾随零的数量

解题思路:当n过大时,从1遍历至n,那么会超时,发现以下规律:

n! = 1 * 2 * 3 * 4 * (1 * 5) * ... * (2 * 5) * ... * (3 * 5) ...
每隔 5 个数就会出现 一个 5,因此我们只需要通过 n / 5 来计算存在存在多少个 5 个数,那么就对应的存在多少个 5
每隔 25 个数会出现 一个 25, 而 25 存在 两个 5,我们上面只计算了 25 的一个 5,
因此需要 n / 25 来计算存在多少个 25
因此 counts = n / 5 + n / 25 + n / 125 + ...   因分母可能过大溢出,上面的式子可以进行转换
counts = n / 5 + n / 5 / 5 + n / 5 / 5 / 5 + ...
代码示例:
  public int trailingZeroes(int n) {
        int count = 0;
        while (n != 0) {
            n /= 5;
            count += n;
        }
        return count;
    }

潜在问题与风险:
边界条件处理:此代码逻辑上处理了常见的整数情况,但没有显式考虑负数或零作为输入的情况。虽然将负数作为参数传入此函数可能没有明显的逻辑错误,因为负数除以5也会得到一个整数(考虑取模),但是将0作为输入则会导致计数器永远为0,这可能是预期之外的行为。对于函数的文档说明,应该明确支持或不支持负数和0作为输入。
异常处理:当前代码没有进行任何形式的异常处理。虽然这个简单的算法不太可能出现运行时异常,但在更复杂的上下文中,考虑到输入参数可能来自不可靠的源,建议添加异常处理逻辑,至少对输入参数进行基本的校验。
优化方向
算法优化:当前算法通过不断地除以5并累加商来计算尾部的0个数,其时间复杂度为O(log n)。这个算法已经相对高效,但对于大数处理,每一步的除法运算仍然有优化空间。例如,可以通过数学方法直接计算出n中因子5的个数,从而避免循环计算。
代码可读性:虽然当前代码逻辑简单,但添加一些注释来解释为什么通过除以5来计算尾部0的个数,以及数学上的解释,可以帮助其他开发者更快地理解代码的意图,从而提升代码的可读性。
性能优化:虽然对于此函数,性能优化的空间有限,但是在循环内部使用基本类型(如int)进行操作可以避免装箱操作,从而略微提升性能。此外,确保trailingZeroes函数尽可能地内联,可以减少调用开销,这对于频繁调用的小函数特别有帮助。
参数验证:考虑添加对输入参数的验证逻辑,例如判断n是否大于等于0。如果是,则正常执行算法;如果不是,则抛出一个有意义的异常或返回一个特定的错误码。这可以增加代码的健壮性。
代码重用性:如果在其他地方也需要进行类似的尾部0的计算,可以考虑将此函数抽象出来作为一个公共工具类的方法,从而提升代码的重用性。
以下是相应的代码优化:

 /**
     * 用于计算给定数n中末尾零的个数。函数中通过循环将n除以5,
     * 并将商累加到计数器count中,直到n不再能整除5为止。
     * 最后返回计数器count的值,即末尾零的个数。
     * 注意:该方法支持非负整数,不支持负数或零作为输入。
     * 
     * @param n 非负整数
     * @return 末尾零的个数
     * @throws IllegalArgumentException 如果n小于或等于零
     */
    public static int trailingZeroes(int n) throws IllegalArgumentException {
        // 校验输入参数
        if (n <= 0) {
            throw new IllegalArgumentException("输入参数n必须为非负整数。");
        }

        int count = 0;
        // 直接使用数学方法优化计算过程,避免除法运算
        while (n >= 5) {
            n = n / 5;
            count += n;
        }
        return count;
    }

标签:count,25,int,代码,个数,算法,尾随,阶乘
From: https://www.cnblogs.com/bwcx1375/p/18113639

相关文章

  • 树模型系列——1、决策树算法简介
    1.决策树简介决策树(decisiontree)是机器学习中一种非参数的监督学习算法,可用于分类与回归。其中分类决策树是基于变量特征对离散变量目标值进行分类的,可用于二分类或多分类;回归决策树是基于变量特征对连续变量目标值进行分类的,可用于连续变量的回归拟合。从上图看,可知树形结构......
  • Java最短路径算法知识点(含面试大厂题和源码)
    最短路径算法是计算机科学和图论中的核心问题之一,它旨在找到从一个顶点到另一个顶点或在所有顶点之间的最短路径。这个问题在多种实际应用中都非常重要,如网络路由、交通规划、社交网络分析等。以下是一些与最短路径算法相关的知识点:Dijkstra算法:由荷兰计算机科学家艾兹......
  • 数据结构与算法分析实验3 [进阶]通过链表实现多项式加法和乘法
    文章目录大致内容介绍多项式加法代码一览头文件Poly.h内容如下:实现文件Poly.cpp内容如下:初始化增加元素删除元素功能函数遍历函数清除销毁打印多项式向多项式内插入一个元素源文件main.cpp内容如下:实现效果:多项式乘法实现方法:在Poly.h中添加声明:在Poly.cpp中添加实现:在......
  • 代码随想录算法训练营三刷day44 | 动态规划之 完全背包 518. 零钱兑换 II 377. 组合总
    三刷day44完全背包基础知识问题描述举个栗子518.零钱兑换II1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组377.组合总和Ⅳ1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例来推导dp......
  • 算法之查找
    1、顺序查找:packagecom.arithmetic.search;//顺序查找//sequentialSearch方法接收一个整数数组和一个目标元素作为参数,并使用顺序查找的方式在数组中查找目标元素。//它通过循环遍历数组元素,逐个与目标元素比较,如果找到了目标元素,则返回其索引位置。//如果遍历完整个数......
  • 深度学习之详解常见梯度算法(概念、公式、原理、算法实现过程)
    目录前言一、如何实现梯度下降?二、梯度计算三、常见的梯度公式及梯度算法常见的梯度公式:1.标量对向量的梯度:2.标量对矩阵的梯度:3.向量对标量的梯度:常见梯度算法:四、常见梯度算法实现 1、批量梯度下降算法实现函数2、随机梯度下降算法实现函数 3、小批量梯度......
  • 吴恩达2022机器学习专项课程(一) 4.6 运行梯度下降&第一周课程实验:线性回归的梯度下降
    问题预览/关键词更新梯度下降对模型拟合,等高线图,3d空间图的变化。什么是批量梯度下降。实验目标计算梯度运行梯度下降梯度下降迭代次数和成本函数的关系可视化模型预测在等高线图上的梯度下降学习率过大报错问题笔记1.模型拟合,等高线图,3d空间图的变化3.5课节有一样的图,......
  • MySQL索引背后的数据结构及算法原理
    摘要本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等。为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MyS......
  • 适用于连续动作空间的强化学习算法-Actor-Critic算法族
    适用于连续动作空间的强化学习算法通常被称为Actor-Critic算法。以下是一些主要的适用于连续动作空间的强化学习算法:DeepDeterministicPolicyGradient(DDPG):DDPG是一种基于Actor-Critic框架的算法,它结合了确定性策略梯度(DeterministicPolicyGradient)和深度神经网络来解......
  • 【数据结构与算法篇】动态顺序表实战项目:通讯录
    【数据结构与算法】动态顺序表实战项目:通讯录......