Description:
Write a program that will calculate the number of trailing zeros in a factorial of a given number.
N! = 1 * 2 * 3 * … * N
Be careful 1000! has 2568 digits…
For more info, see: http://mathworld.wolfram.com/Factorial.html
单词说明 :
factorial,adj.因子的, 阶乘的; n. 阶乘
Examples
zeros(6) = 1
# 6! = 1 * 2 * 3 * 4 * 5 * 6 = 720 --> 1 trailing zero
zeros(12) = 2
# 12! = 479001600 --> 2 trailing zeros
Hint: You’re not meant to calculate the factorial. Find another way to find the number of zeros.
单词说明 :
hint,n.暗示, 线索; v.暗示, 示意
Test Cases:
test_that("Fixed tests", {
expect_equal(zeros(0), 0)
expect_equal(zeros(6), 1)
expect_equal(zeros(30), 7)
expect_equal(zeros(100), 24)
expect_equal(zeros(1000), 249)
expect_equal(zeros(100000), 24999)
expect_equal(zeros(1000000000), 249999998)
})
test_that("Random tests", {
solution = function(n) {
r = 0
while (n > 0) {
n = n %/% 5
r = r + n
}
r
}
for (i in 1:100) {
n = floor(runif(1, 0, 1001))
result = solution(n)
expect_equal(zeros(n), result)
}
for (i in 1:100) {
n = floor(runif(1, 1001, 1000001))
result = solution(n)
expect_equal(zeros(n), result)
}
for (i in 1:100) {
n = floor(runif(1, 1000001, 1000000001))
result = solution(n)
expect_equal(zeros(n), result)
}
})
我的代码
zeros <- function(n){
ifelse(n<5, 0, n%/%5+Recall(n%/%5))
}
代码当中设计到的原理是这样的:
令f(x)表示正整数x末尾所含有的“0”的个数,则有:
①当0 < n < 5时,f(n!) = 0;
②当n >= 5时,f(n!) = k + f(k!), 其中 k = n / 5(取整)。
从而可以递归求解。
讲到递归,不知道有没有人发现我在代码中用到了Recall
函数,这种函数讲道理是我新学会的,下面我贴一段R语言帮助文档给出的解释:
Recall {base}
Recursive Calling(递归调用)
Description:
Recall is used as a placeholder for the name of the function in which it is called. It allows the definition of recursive functions which still work after being renamed, see example below.
Examples:
## A trivial (but inefficient!) example:
fib <- function(n)
if(n<=2) { if(n>=0) 1 else 0 } else Recall(n-1) + Recall(n-2)
fibonacci <- fib; rm(fib)
## renaming wouldn't work without Recall
fibonacci(10) # 55
简单来说,Recall
就是替换被递归调用的函数名,我尝试过把上面帮助文档中的Recall
换成fib
,结果将会完全不一样,会出现这么个错误:Error in fib(n - 1) : 没有"fib"这个函数
,原因是代码中把fib
赋给fibonacci
之后又把它给删了,所以在递归调用的时候调不到fib
,从而导致出问题。但如果把递归函数中的fib
换为Recall
却可以正常调用,也就是说提高了函数的稳定性与可用性。