繁体   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