793. 阶乘函数后 K 个零

133 阅读1分钟

题目表述

f(x) 是 x! 末尾是 0 的数量。回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 。

例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 ;而 f(11) = 2 ,因为 11!= 39916800 末端有 2 个 0 。 给定 k,找出返回能满足 f(x) = k 的非负整数 x 的数量。

示例 1:

输入:k = 0
输出:5
解释:0!, 1!, 2!, 3!, 和 4! 均符合 k = 0 的条件。

示例 2:

输入:k = 5
输出:0
解释:没有匹配到这样的 x!,符合 k = 5 的条件。

示例 3:

输入: k = 3
输出: 5

提示:

0<=k<=1090 <= k <= 10^9

思路

本题的思路就是找到符合k的最大值和最小值,然后相减即可。这就是寻找左右边界的问题,可以用二分查找的方法。

这里的主要问题就是范围的问题。由于k的范围到10910^9,所以在实现时要使用Long类型。

class Solution {
    public int preimageSizeFZF(int k) {
        return (int)(rightBound(k) - leftBound(k) + 1);
    }
    //计算num!中末尾为0的数量
    public long countZeros(long num) {
        long res = 0;
        for (long temp = num; temp / 5 > 0; temp /= 5) {
            res += temp / 5;
        }
        return res;
    }
    public long rightBound(int k) {
        long left = k, right = Long.MAX_VALUE;
        while (left < right) {
            long mid = left + ((right - left) >> 1);
            if (countZeros(mid) < k) {
                left = mid + 1;
            } else if (countZeros(mid) > k) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left - 1;
    }
    public long leftBound(int k) {
        long left = k, right = Long.MAX_VALUE;
        while (left < right) {
            long mid = left + ((right - left) >> 1);
            if (countZeros(mid) < k) {
                left = mid + 1;
            } else if (countZeros(mid) > k) {
                right = mid;
            } else {
                right = mid;
            }
        }
        return left;
    }
}