簡體   English   中英

Function 得到 3、5、7 的所有數字的總和,直到 1000

[英]Function to get the sum of all numbers multiples of 3, 5, 7 until 1000

computeMultiplesSum (n)方法應返回嚴格小於n357的所有正倍數的總和

例如,對於n = 11 ,我們得到3、5、6、7、9、10作為倍數,這些倍數的總和是40

實現computeMultiplesSum (n)

約束: 0 = <n <1000

public class Solution_Multiple {

    public static int computeMultiplesSum(int n) {
        int sum=0;
        for(int i=0;i<n;i++)
            if(i%3 == 0|| i%5 == 0||i%7 == 0)
                sum+=i;
        return sum;
    }

    public static void main(String[] args) {
        System.out.println(Solution_Multiple.computeMultiplesSum(11));

    }
}

但是我通過運行上面的代碼得到的結果是: 420而不是40

如何修復其他代碼以獲得40的結果?

由於您的代碼很好,因此可以按預期工作。 然而,模算子是低效的。 更快的實現將是這樣的:

   static int computeMultiplesSum2(int n){
        int x3 = 0,x5 = 0, x7 = 0;
        int x15 = 0, x21 = 0, x35 = 0;
        int x105 = 0;

        for(int i = 3; i < n; i+=3)      x3 += i;
        for(int i = 5; i < n; i+=5)      x5 += i;
        for(int i = 7; i < n; i+=7)      x7 += i;
        for(int i = 15; i < n; i+=15)    x15 += i;
        for(int i = 21; i < n; i+=21)    x21 += i;
        for(int i = 35; i < n; i+=35)    x35 += i;
        for(int i = 105; i < n; i+=105)  x105 += i;

        return x3 + x5 + x7 - x15 - x21 - x35 + x105;
    }

在這個解決方案中,我必須取出 15、21 和 35 的倍數,因為:

  • 3 和 5 有 15 作為倍數;
  • 3 和 7 有 21 作為倍數;
  • 5 和 7 的倍數為 35。

由於 105 可以被 3、5、7 整除,所以會被加 3 次,因為它可以被 15、21、35 整除,所以會被刪除 3 次,所以我們需要在最后加上,否則我們會刪除太多。

另一個更好的解決方案(時間復雜度為O(1) )是采用數學方法。

您正在嘗試對所有數字求和,例如 3 + 6 + 9 + 12... 1000 和 5 + 10 + 15 +20 +... 10000 這與 3 * (1 + 2 + 3 + 4 + ... + 333) 和 5 * ( 1 + 2 + 3 + 4 +... + 200),'n' 自然數之和是 (n * (n + 1)) (source ) 所以你可以計算恆定時間如下:

static int computeMultiplesSum3(int n){
    int x3 =    (n - 1) / 3;                      // 3 * ( 1 +2 + 3 … (n-1)/3)
    int x5 =    (n - 1) / 5;                      // 5 * ( 1 +2 + 3 … (n-1)/5)
    int x7 =    (n - 1) / 7;
    int x15 =   (n - 1) / 15;
    int x21 =   (n - 1) / 21;
    int x35 =   (n - 1) / 35;
    int x105 =  (n - 1) / 105;
    int sn3 =   (x3 * (x3 + 1)) / 2;
    int sn5 =   (x5 * (x5 + 1)) / 2;
    int sn7 =   (x7 * (x7 + 1)) / 2;
    int sn15 =  (x15 * (x15 + 1))/ 2;
    int sn21 =  (x21 * (x21 + 1))/ 2;
    int sn35 =  (x35 * (x35 + 1))/ 2;
    int sn105 = (x105 * (x105 + 1))/2;
    return (3*sn3) + (5 *sn5) + (7 * sn7) - (15*sn15) - (21 *sn21) - (35 * sn35)
            + (105 * sn105);
}

代碼完全按照您的要求執行,如果您沒有將 sum 初始化為 3 並提供 '11' 作為實際參數,您將得到您想要的。

假設 sum = 0 在開始求和之前,則 3、5 和 7 的所有倍數 < 40 (0 + 3 + 5 + 6 + 7 + 9 + 10 + 12 + 14 + 15 + 18 + 20 + 21 + 24 + 25 + 27 + 28 + 30 + 33 + 35 + 36 + 39) = 417

在 if 正文中添加 print 語句以通過循環獲取 i 的 state:

                System.out.print(i+" + ");

這是一種使用Set<Integer>檢測重復項的方法,但我仍然認為必須有一個更數學的解決方案,可以針對更大的n值(例如1,000,000 )擴展到任意數量的素因子。 我不喜歡嵌套循環或使用集合。

public static int computeMultipleSums(int n) {
    Set<Integer> dups = new HashSet<>();
    int sum = 0;
    int[] primeFactors = {3,5,7};
    for (int p : primeFactors) {
        for (int i = p; i < n; i += p) {
            sum += dups.add(i) ? i : 0;
        }
    }
    return sum;
}

更好的、可擴展的方法是使用BitSet 通過設置因子的所有倍數,可以捕獲重復項,因為它們只是再次設置並且不會將任何內容添加到總和中。

  • 下面循環中的(n+(f-1))/f確保當f整除和不整除n時終止是一致的
  • long用於求和以適應較大的n
public static long computeMultipleSumsBit(int n) {
    BitSet b= new BitSet();
    int[] factors = {3,5,7};
    for (int f : factors) {
        for (int i = 1; i < (n+(f-1))/f; i++) {
            b.set(f*i); // set the ith position of f
        }
    }
    return b.stream().mapToLong(a->a).sum();
}

不是那么優雅,但要解決 O(1) 復雜性,但還要考慮到不要多次添加公倍數,這里有一個替代方案:

public static int computeMultiplesSum(int n) {
    n--;
    int multiplesCount = 0;
    int sum = 0;
    if (n >= 3) {
        multiplesCount = n / 3;
        sum += (multiplesCount * (3 + multiplesCount * 3)) / 2;
    }
    if (n >= 5) {
        multiplesCount = n / 5;
        sum += (multiplesCount * (5 + multiplesCount * 5)) / 2;
    }
    if (n >= 7) {
        multiplesCount = n / 7;
        sum += (multiplesCount * (7 + multiplesCount * 7)) / 2;
    }
    if (n >= 15) {   // 3 * 5
        multiplesCount = n / 15;
        sum -= (multiplesCount * (15 + multiplesCount * 15)) / 2;
    }
    if (n >= 21) {   // 3 * 7
        multiplesCount = n / 21;
        sum -= (multiplesCount * (21 + multiplesCount * 21)) / 2;
    }
    if (n >= 35) {   // 5 * 7
        multiplesCount = n / 35;
        sum -= (multiplesCount * (35 + multiplesCount * 35)) / 2;
    }
    if (n >= 105) {   // 3 * 5 * 7
        multiplesCount = n / 105;
        sum += (multiplesCount * (105 + multiplesCount * 105)) / 2;
    }
    return sum;
}

暫無
暫無

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

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