簡體   English   中英

返回Java中的素數因子串

[英]Returning String of prime factors in Java

我知道這是一個經典問題。 我用Java解決了它。 我的解決方案如下。 但是,當我在codefights.com中使用此解決方案時,它超出了執行時間限制。 如果有人能以任何可能的方式向我提出改進此代碼的建議,我將不勝感激。 請隨意批評我的代碼,以便我可以提高我的編碼技能。 謝謝

你被賦予了數字n。

返回n作為其主要因素的產物。

對於n = 22,輸出應為“2 * 11”。

對於n = 120,輸出應為“2 * 2 * 2 * 3 * 5”。

對於n = 17194016,輸出應為“2 * 2 * 2 * 2 * 2 * 7 * 59 * 1301”。

[輸入]整數n

小於109的整數。[輸出]字符串

由*符號分割的n的素數因子。 主要因素應該是遞增的順序。

解決方案(JAVA):

public String primefactors(int n) {
    String factors = "";

    for (int i = 2; i <= n / 2; i++) {
        if (isPrime(i)) {
            while (n % i == 0) {
                n /= i;
                if (isPrime(n) && n != 1) {
                    factors = factors + Integer.valueOf(i).toString() + "*"
                            + Integer.valueOf(n).toString();
                    break;
                } else if (n == 1)
                    factors = factors + Integer.valueOf(i).toString();
                else
                    factors = factors + Integer.valueOf(i).toString() + "*";
            }
        }
    }
    return factors;
}

public boolean isPrime(int n) {
    boolean prime = true;
    if (n == 1)
        return false;
    else if (n % 2 == 0 && n!=2)
        return false;
    else if (n % 3 == 0 && n!=3)
        return false;
    else {
        for (int j = 2; j < n / 2; j++) {
            if (n % j == 0) {
                return false;
            }
        }
    }
    return prime;
}

由於n小於固定數(109),只需使用包含所有prims <= 109的表,而不是動態生成它們。 或至少首先使用erathostenes或atkin的篩子產生prims。 硬編碼表會更好,但使用篩子動態生成表格也會加快速度。 您實現的isPrime()函數是性能殺手。

函數primefactors isPrime()primefactors被調用太多次。 例如, i == 2並且n有許多除數2 熱門電話(isPrime(i))很好。 但是,在循環內部while (n % i == 0) ,在每次除以n /= 2;之后檢查isPrime(n) n /= 2; 因此,如果初始n100則函數isPrime()被調用50 ,而下一個循環被調用25 這沒有任何意義。 我認為這是最大的問題,因為即使isPrime在線性時間內工作,在內部循環中多次調用它也是太多了。

在兩種情況下可以從i的循環中退出: n在除法之后等於1 ,或者如果i大於sqrt(n)n肯定是素數。

public String primefactors(int n) {
    String factors = "";
    int max_divisor = sqrt(n);
    for (int i = 2; i <= max_divisor; i++) {
        if (isPrime(i)) {
            while (n % i == 0) {
                n /= i;
                if (n == 1)
                    factors = factors + Integer.valueOf(i).toString();
                else
                    factors = factors + Integer.valueOf(i).toString() + "*";
            }
            max_divisor = sqrt(n);
        }
    }
    // check for the last prime divisor
    if (n != 1)
        factors = factors + Integer.valueOf(n).toString();

    return factors;
}

即便之后改善(和sqrt(n)作為最大極限isPrime()你的算法將有線性復雜度O(n)因為有最多sqrt(n)循環對i和探針黃金的最大數量in isPrime也是sqrt(n)


是的,通過為isPrime()選擇更好的算法可以做得更好。 即使您不允許使用硬編碼的素數表,也可以在運行時生成這樣的查找表(如果有足夠的內存)。 因此,可以使用按升序組織的自動生成的素數列表來探測最大為sqrt(n )的給定數量。 如果i變得大於sqrt(n)則意味着找到下一個素數並且它應該被附加到查找表中並且isPrime()應該返回true

假設isPrime被調用為113 在那一刻,查找表有一個以前的素數列表: 2,3,5,7,11,13... 因此,我們嘗試將113從該列表中的項目除以sqrt(113)while (i <= 10) )。 在嘗試2,3,5,7之后,列表11上的下一個項目太大,因此將113添加到素數列表中,並且函數返回true


在最壞的情況下,其他算法可以提供更好的性能。 例如,Eratosthenes篩或Atkin篩可用於有效預先計算的素數列表,直到給定n具有最佳O(n)復雜度以實現最佳實施。 在這里,你需要找到所有素數到sqrt(n) ,所以需要O(sqrt(n))來生成這樣的列表。 生成這樣的列表后,您需要嘗試按數字划分輸入是最多需要sqrt(n)探測的列表。 因此,算法復雜度為O(sqrt(n)) 但是,假設你輸入10242到的功率10 在這種情況下,第一個算法會更好,因為它不會去大於2素數。


你真的需要函數isPrime()嗎?

靈活思考如果我們仔細觀察,您似乎不必在某個范圍內搜索所有素數。 您只需要找到一個給定整數的所有素數除數。 但是,如果我們嘗試將n除以范圍內的所有整數除以sqrt(n) ,這也是很好的解決方案。 即使這樣的整數不是素數,它也會因條件n % i == 0而被跳過,因為所有低於被測整數的質數都已從n刪除,因此簡單的模塊化除法與isPrime()相同。 O(sqrt(n))復雜度的完整解決方案:

public String primefactors(int n) {
    String factors = "";
    int max_divisor = sqrt(n);
    for (int i = 2; i <= max_divisor; i++) {
        while (n % i == 0) {
            n /= i;
            max_divisor = sqrt(n);
            if (n == 1)
                factors = factors + Integer.valueOf(i).toString();
            else
                factors = factors + Integer.valueOf(i).toString() + "*";
        }
    }
    // check for the last prime divisor
    if (n != 1)
        factors = factors + Integer.valueOf(n).toString();

    return factors;
}

也可以拆分函數以避免if (n == 1)檢查內循環,但是它不會改變算法的復雜性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM