LeetCode - Easy - 172. Factorial Trailing Zeroes

Topic

  • Math

Description

https://leetcode.com/problems/factorial-trailing-zeroes/

Given an integer n, return the number of trailing zeroes in n!.

Follow up: Could you write a solution that works in logarithmic time complexity?

Example 1:

Input: n = 3
Output: 0
Explanation: 3! = 6, no trailing zero.

Example 2:

Input: n = 5
Output: 1
Explanation: 5! = 120, one trailing zero.

Example 3:

Input: n = 0
Output: 0

Constraints:

  • 0 <= n <= 10⁴

Analysis

方法一:暴力算法(用到Java的BigInteger)。

方法二:分析成阶乘后出现0的情况。

出现0情况是乘子中有5, 10, 15…等5的整数倍的数。

5可与偶数乘子相乘等出10的整数倍,而且偶数个数是明显大大多于5的整数倍的数,于是一个数阶乘后低位出现0的个数有至少有 n / 5 个。

另外注意乘子中有25, 125, 625…5的整数幂的整数倍(如50, 75, 100, 250 …),25 = 5 * 5,125 = 5 * 5 * 5,625 = 5 * 5 * 5 * 5,额外的5需要更多偶数与它们配对。也就是说一个数阶乘后低位出现0的个数有 n / 5 + n / 25 + n / 125 + n / 625… 。这样程序基本成型。

方法三:别人写的,更精简。

Submission

import java.math.BigInteger;

public class FactorialTrailingZeroes {

	// 方法一:暴力算法
	public int trailingZeroes1(int n) {
		int result = 0;
		BigInteger num = factorial(n);
		while (num.mod(BigInteger.TEN).equals(BigInteger.ZERO)) {
			result++;
			num = num.divide(BigInteger.TEN);
		}
		return result;
	}

	public BigInteger factorial(int n) {
		BigInteger product = BigInteger.valueOf(1);
		for (int i = n; i > 0; i--)
			product = product.multiply(BigInteger.valueOf(i));
		return product;
	}

	// 方法二:根据方法一规律可得
	public int trailingZeroes2(int n) {
		// if(n == 0) return 0;
		int num = (int) (Math.log(n) / Math.log(5));
		int result = 0;
		while (num > 0)
			result += (n / (int) Math.pow(5, num--));
		return result;
	}

	// 方法三:别人写的,更精简
	public int trailingZeroes3(int n) {
		return n == 0 ? 0 : n / 5 + trailingZeroes3(n / 5);
	}
}

Test

import static org.junit.Assert.*;
import org.junit.Test;

public class FactorialTrailingZeroesTest {

	@Test
	public void test1() {
		FactorialTrailingZeroes obj = new FactorialTrailingZeroes();

		assertEquals(0, obj.trailingZeroes1(3));
		assertEquals(1, obj.trailingZeroes1(5));
		assertEquals(0, obj.trailingZeroes1(0));
		
		assertEquals(0, obj.trailingZeroes2(3));
		assertEquals(1, obj.trailingZeroes2(5));
		assertEquals(0, obj.trailingZeroes2(0));
		
		for(int i = 0; i <= 1000; i++) {
			//System.out.println(String.format("trailingZeroes(%d) : %d : %d", i, obj.trailingZeroes1(i), obj.trailingZeroes2(i)));
			assertEquals(obj.trailingZeroes1(i), obj.trailingZeroes2(i));
		}
	}
	
	@Test
	public void test2() {
		FactorialTrailingZeroes obj = new FactorialTrailingZeroes();
		for(int i = 0; i <= 1000; i++) {
			assertEquals(obj.trailingZeroes1(i), obj.trailingZeroes3(i));
		}
	}
	
	@Test
	public void testfactorial() {
		FactorialTrailingZeroes obj = new FactorialTrailingZeroes();
		assertEquals("265252859812191058636308480000000", obj.factorial(30).toString());
	}
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值