题目
类型:二分、数学
解题思路
题目大意很重要!!
本题意思:给你一个非负整数 K,问你有多少个 n,使得 n! 结果末尾有 K 个 0。
搜索有多少个 n 满足 trailingZeroes(n) == K,其实就是在问,满足条件的 n 最小是多少,最大是多少,最大值和最小值一减,就可以算出来有多少个 n 满足条件了,其实就是 二分查找 中「搜索左侧边界」和「搜索右侧边界」这两个事儿
这道题目实际上给了限制,K 是在[0, 10^9]区间内的整数,也就是说,trailingZeroes(n) 的结果最多可以达到 10^9。
然后我们可以反推,当 trailingZeroes(n)结果为 10^9 时,n 为多少?这个不需要你精确计算出来,你只要找到一个数 hi,使得 trailingZeroes(hi)比 10^9大,就可以把 hi 当做正无穷,作为搜索区间的上界。trailingZeroes函数是单调函数,那我们就可以猜,先算一下 trailingZeroes(INT_MAX)的结果,比10^9小一些,那再用 LONG_MAX 算一下,远超 10^9了,所以LONG_MAX可以作为搜索的上界。
代码
class Solution {public int preimageSizeFZF(int K) {// 左边界和右边界之差 + 1 就是答案return (int)(rightBound(K) - leftBound(K) + 1);}// 逻辑不变,数据类型全部改成 longlong trailingZeroes(long n) {long res = 0;for (long d = n; d / 5 > 0; d = d / 5) {res += d / 5;}return res;}/* 搜索 trailingZeroes(n) == K 的左侧边界 */long leftBound(int target) {long lo = 0, hi = Long.MAX_VALUE;while (lo < hi) {long mid = lo + (hi - lo) / 2;if (trailingZeroes(mid) < target) {lo = mid + 1;} else if (trailingZeroes(mid) > target) {hi = mid;} else {hi = mid;}}return lo;}/* 搜索 trailingZeroes(n) == K 的右侧边界 */long rightBound(int target) {long lo = 0, hi = Long.MAX_VALUE;while (lo < hi) {long mid = lo + (hi - lo) / 2;if (trailingZeroes(mid) < target) {lo = mid + 1;} else if (trailingZeroes(mid) > target) {hi = mid;} else {lo = mid + 1;}}return lo - 1;}}
