1. 程式人生 > 其它 >172. 階乘後的零— —力扣每日一題

172. 階乘後的零— —力扣每日一題

172. 階乘後的零— —2022/3/25

1、題目

給定一個整數 n ,返回 n! 結果中尾隨零的數量。

提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1

2、示例

1)示例1

輸入:n = 3
輸出:0
解釋:3! = 6 ,不含尾隨 0

2)示例2

輸入:n = 5
輸出:1
解釋:5! = 120 ,有一個尾隨 0

3)示例3

輸入:n = 0
輸出:0

3、解答

3.1 思路及具體操作

  • 初步的思路還是計算出階乘之後的數,來計算0的個數
  • 由於java給出的基本資料型別最大的長度也僅僅很小,所以不能直接使用基本資料型別去做
  • 這裡想的初步思路是使用陣列+字串
    的方式計算階乘的值
  • 計算的值也是使用陣列去儲存
    • trailingZeroes(int n)計算0的個數
    • transform(int n)將整數轉換成整型陣列
    • factorial(int n)計算n!的值
    • factorials(int[] m,int[] n)計算mn的乘積

3.2 程式碼

/*本方法採用陣列儲存階乘的資料,然後根據陣列判斷0的個數
* 雖然解決了辦法,但是超出了時間限制,很難受
*  */
public class Solution {
    public static void main(String[] args) {
        int[] arr = factorial(100);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]);
        }
        System.out.println("\n"+arr.length);
        System.out.println(trailingZeroes(100));
    }

    //判斷n階乘0的個數
    public static int trailingZeroes(int n) {
        if(n == 0){
            return 0;
        }
        int m = 0;
        int[] intArr = factorial(n);
        for (int i = intArr.length -1; i >= 0; i--) {
            if(intArr[i] == 0){
                m++;
            }else{
                break;
            }
        }
        return m;
    }

    //整型轉換成陣列
    public static int[] transform(int n){
        String ms = "" + n + "";
        char[] msc = ms.toCharArray();
        int[] intArr = new int[msc.length];
        for (int i = 0; i < msc.length; i++) {
            intArr[i] = (int) msc[i] - 48;
        }
        return intArr;
    }

    //用陣列儲存階乘的資料
    public static int[] factorial(int n){
        int nums = n;
        int[] result = new int[n];
        int num = n;
        for (int i = 0; i < nums; i++) {
            if(i==0){
                result = factorials(transform(num),transform(num-1));
                num --;
            }else{
                if(num == 1){
                    break;
                }
                num --;
                result = factorials(result,transform(num));
            }
        }
        int a = 0;
        int b = 0;
        for (int i = 0; i < result.length; i++) {
            if(result[i] != 0){
                a = result.length - i;
                b = i;
                break;
            }
        }
        int[] results = new int[a];
        for (int i = 0; i < a; i++) {
            results[i] = result[b+i];
        }
        return results;
    }

    //返回兩個數相乘的結果,返回結果為陣列
    public static int[] factorials(int[] m,int[] n) {
        int result[] = new int[m.length+n.length];
        for(int i = 0; i < m.length; i++){
            for(int j = 0; j < n.length; j++){
                result[result.length-1-i - j] += (m[m.length-1-i] * n[n.length-1-j])%10;
                result[result.length-i - j - 2] += (m[m.length-1-i] * n[n.length-1-j])/10;
            }
        }
        return result;
    }
}

3.3 思考

  • 其實計算出階乘的值這個方法是由於想要再練習一下階乘的計算,所以採用的直接法做
  • 但是本題的實質其實是計算尾部 0 的個數,因此只需要明白什麼樣的值才能使得尾部可以為0

4、優化解法

4.1 優化思路

  • 尾部 0 的產生是由於 10 的出現,所以只需要判斷乘數中會出現的 10 的個數就可以判斷出尾部 0 的個數
  • 那我們就需要知道 10 可以是 5 與 2 的乘積,所以可以採用判斷 5 的個數(所有5的公倍數相當於5*公倍數個5)
  • 因為5在2之後,所以不需要考慮 2 的個數問題

4.2 程式碼

public static int trailingZeroes(int n) {
    int num = 0;
    for (int i = 5; i <= n; i+=5) {
        for (int x = i; x % 5 == 0; x /= 5) {
            num++;
        }
    }
    return num;
}