【阶乘】
一、阶乘后的零:
LeetCode172
链接:
172.阶乘后的零
题目:

思路:
0的产生是一定是因为2*5产生的,所以就是找因数
 并且,可想而知,找的到因数5,必然找的到因数2与之搭配(只要是偶数就可以找的到2)
 👉 题目转化为找因数5的个数
代码:
/**
 * @param {number} n
 * @return {number}
 */
var trailingZeroes = function(n) {
    let res = 0
    for(; n/5 > 0; n/=5) {
        res += Math.floor(n/5)
        // 这里一定要加一下Math.floor 不然结果是错的
    }
    return res
};
二、阶乘函数后K个零
LeetCode793
链接:
793.阶乘函数后K个零
题目:

思路:
这道题就是利用一个求阶乘尾数为0的数量的函数,再利用二分查找寻找到尾数为0的数量是k的左右边界,从而得出这样的数有多少个
👉 参考 172.阶乘后的零 中求阶乘后尾数0的数量的函数
 👉 参考 34.在排序数组中查找元素的第一个和最后一个位置 中二分查找找到左右边界的函数
代码:
/**
 * @param {number} k
 * @return {number}
 */
var preimageSizeFZF = function(k) {
    return right_bound(k) - left_bound(k) + 1
};
var trailingZero = function(d) {
    let res = 0
    for(; d/5 > 0; d/=5) {
        res += Math.floor(d/5)
    }
    return res
}
var left_bound = function(target) {
    let left = 0, right = Number.MAX_VALUE-1
    while(left <= right) {
        let mid = left + Math.floor((right - left) / 2)
        if(trailingZero(mid) >= target) {
            right = mid - 1
        } else {
            left = mid + 1
        }
    }
    return left
}
var right_bound = function(target) {
    let left = 0, right = Number.MAX_VALUE-1
    while(left <= right) {
        let mid = left + Math.floor((right - left) / 2)
        if(trailingZero(mid) <= target) {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return right
}
附:二分查找寻找左右边界的模板(JS版)
1 寻找左侧边界的二分搜索
var left_bound = function(nums, target) {
    let left = 0, right = nums.length - 1;
    // 搜索区间为 [left, right]
    while (left <= right) {
        let mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            // 搜索区间变为 [mid+1, right]
            left = mid + 1;
        } else if (nums[mid] > target) {
            // 搜索区间变为 [left, mid-1]
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 收缩右侧边界
            right = mid - 1;
        }
    }
    // 判断 target 是否存在于 nums 中
    // 此时 target ⽐所有数都⼤,返回 -1
    if (left == nums.length) return -1;
    // 判断⼀下 nums[left] 是不是 target
    return nums[left] == target ? left : -1;
}
2 寻找右侧边界的二分搜索
var right_bound = function(nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) {
        let mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
        // 这⾥改成收缩左侧边界即可
            left = mid + 1;
        }
    }
    // 最后改成返回 left - 1
    if (left - 1 < 0) return -1;
    return nums[left - 1] == target ? (left - 1) : -1;
}
写在最后:
 二分查找有点感觉了
 继续刷!冲!



















