【阶乘】
一、阶乘后的零:
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;
}
写在最后:
二分查找有点感觉了
继续刷!冲!