Codewars题目中Python函数return大数返回0但print正确的问题求助
问题描述
我在Codewars的一道题目中遇到了问题:我编写的count_zeros_n_double_fact函数,使用return返回结果时能通过小测试,但处理大数时返回0;将return改为print输出后,所有结果都正确。相关代码如下,请求帮助排查原因。
原return版本代码:
def count_zeros_n_double_fact(n): res = [] oddeven = [] revers = [] result = 1 c = 0 for i in range(n+1): if i % 2 == 0 and i != 0: oddeven.append(i) for x in oddeven: result = result * x for z in reversed(str(result)): if z == '0': c+=1 else: break return c
print版本代码:
def count_zeros_n_double_fact(n): res = [] oddeven = [] revers = [] result = 1 c = 0 for i in range(n+1): if i % 2 == 0 and i != 0: oddeven.append(i) for x in oddeven: result = result * x for z in reversed(str(result)): if z == '0': c+=1 else: break print (c)
问题根源
你当前的写法是直接计算双阶乘的实际值,再转成字符串统计末尾0的数量。这种方法在n较小时没问题,但当n很大时会触发两个致命问题:
- 计算超时:大数乘法需要消耗大量CPU时间,在Codewars的超时限制内无法完成计算,测试框架会直接判定结果为0(或默认错误值)。
- 内存溢出:极大的整数转字符串时会占用巨量内存,可能导致Python无法生成完整的数字字符串,此时
str(result)可能丢失末尾部分内容,统计出的0的数量自然为0。
你用print版本时能得到正确结果,大概率是本地测试时等待了足够长的时间让程序完成计算;但return版本在Codewars的自动化测试中,因为超时或内存问题被判定为错误返回0。
正确解法:统计因子数量而非计算实际值
末尾的0由因子2*5产生,每一对2和5就会生成一个末尾0。对于偶数的双阶乘n!! = n*(n-2)*...*2,可以拆解为2^(n/2) * (n/2)!,其中(n/2)!中因子2的数量远多于5,所以末尾0的数量完全由(n/2)!中因子5的总数决定。如果n是奇数,双阶乘是连续奇数相乘,没有因子5,末尾0数量为0。
优化后的代码:
def count_zeros_n_double_fact(n): if n % 2 != 0: return 0 k = n // 2 count = 0 # 统计k!中因子5的总数 while k > 0: k = k // 5 count += k return count
代码说明
- 先判断n是否为奇数,奇数双阶乘无因子5,直接返回0。
- 计算
k = n//2,将偶数双阶乘的问题转化为统计k!中5的因子数量。 - 循环统计
k!中5的因子总数:每次将k除以5,累加商的值(因为每5个数贡献1个5,每25个数额外多贡献1个,以此类推)。
这种方法不需要计算任何大数,时间复杂度为O(log₅n),效率极高,完全不会出现超时或内存问题。
内容的提问来源于stack exchange,提问作者Fenx
相关产品推荐
相关产品推荐

