简体   繁体   English

Function 得到 3、5、7 的所有数字的总和,直到 1000

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

The computeMultiplesSum (n) method should return the sum of all positive multiples of 3 or 5 or 7 that are strictly less than n . computeMultiplesSum (n)方法应返回严格小于n357的所有正倍数的总和

For example, for n = 11 , we get 3, 5, 6, 7, 9, 10 as multiples and the sum of those multiples is 40 .例如,对于n = 11 ,我们得到3、5、6、7、9、10作为倍数,这些倍数的总和是40

Implement computeMultiplesSum (n) .实现computeMultiplesSum (n)

constraints: 0 = <n <1000约束: 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));

    }
}

But the result I get by running the above code is: 420 rather than 40 .但是我通过运行上面的代码得到的结果是: 420而不是40

How can I fix my code in other to get 40 as the result?如何修复其他代码以获得40的结果?

As it is your code is fine, it works as intended.由于您的代码很好,因此可以按预期工作。 Nevertheless, the modulus operator is inefficient.然而,模算子是低效的。 A faster implementation would be something like this:更快的实现将是这样的:

   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;
    }

In this solution, I had to take out the multiples of 15, 21, and 35 because:在这个解决方案中,我必须取出 15、21 和 35 的倍数,因为:

  • 3 and 5 have 15 as multiple; 3 和 5 有 15 作为倍数;
  • 3 and 7 have 21 as multiple; 3 和 7 有 21 作为倍数;
  • 5 and 7 have 35 as multiple. 5 和 7 的倍数为 35。

And since 105 is divisible by all 3, 5, 7, it will be added three times, and because it is divisible by 15, 21, 35 it will be removed three times, therefore we need to added in the end because otherwise we would be removing too much.由于 105 可以被 3、5、7 整除,所以会被加 3 次,因为它可以被 15、21、35 整除,所以会被删除 3 次,所以我们需要在最后加上,否则我们会删除太多。

Another even better solution (with a time complexity of O(1) ) is if you take a mathematical approach.另一个更好的解决方案(时间复杂度为O(1) )是采用数学方法。

You are trying to sum all numbers like this 3 + 6 + 9 + 12... 1000 and 5 + 10 + 15 +20 +... 10000 this is the same of having 3 * (1 + 2 + 3 + 4 + … + 333) and 5 * ( 1 + 2 + 3 + 4 +... + 200), the sum of 'n' natural number is (n * (n + 1)) (source ) so you can calculate in a constant time as follows:您正在尝试对所有数字求和,例如 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);
}

The code is doing exactly as you asked it, and if you hadn't initialized sum to 3 and provided the '11' as the actual parameter you'd have gotten what you wanted.代码完全按照您的要求执行,如果您没有将 sum 初始化为 3 并提供 '11' 作为实际参数,您将得到您想要的。

Assuming sum = 0 before starting the summation, then all multiples of 3, 5 and 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假设 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

add print statement in the if body to get i's state through the loop:在 if 正文中添加 print 语句以通过循环获取 i 的 state:

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

Here is a way to detect duplicates using a Set<Integer> But I still think there has to be a more mathematical solution that scales to any number of prime factors for even larger values of n (eg 1,000,000 ).这是一种使用Set<Integer>检测重复项的方法,但我仍然认为必须有一个更数学的解决方案,可以针对更大的n值(例如1,000,000 )扩展到任意数量的素因子。 I'm not fond of the nested loops or the use of a set.我不喜欢嵌套循环或使用集合。

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;
}

A better, scaleable approach is to use BitSet .更好的、可扩展的方法是使用BitSet By setting all multiples of the factors, the duplicates are caught as they are simply set again and don't add anything to the overall sum.通过设置因子的所有倍数,可以捕获重复项,因为它们只是再次设置并且不会将任何内容添加到总和中。

  • (n+(f-1))/f in the loop below ensures that the termination is consistent when f does and does not divide n下面循环中的(n+(f-1))/f确保当f整除和不整除n时终止是一致的
  • long is used for the sum to accommodate larger values of 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();
}

Not so elegant but to address the O(1)complexity but also taking into account not to add common multiples multiple times, here is an alternative:不是那么优雅,但要解决 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