减少时间复杂度/优化解决方案

时间:2017-08-04 20:29:38

标签: java math

座右铭是找到N以下3或5的所有倍数之和。

这是我的代码:

public class Solution
 {
 public static void main(String[] args)
  {
    Scanner in = new Scanner(System.in);
    int t = in.nextInt();
    long n=0;
    long sum=0;

    for(int a0 = 0; a0 < t; a0++)
    {
        n = in.nextInt();
        sum=0;
         for(long i=1;i<n;i++)
        {
        if(i%3==0 || i%5==0)

            sum = sum + i;
        }
   System.out.println(sum); 
    }
 }
}

对于某些测试用例,执行时间超过1秒。谁能帮助我,以减少时间的复杂性?

4 个答案:

答案 0 :(得分:1)

我们可以找到低于d的{​​{1}}的所有倍数的总和,作为算术级数的总和(它们的总和等于N)。

d + 2*d + 3*d + ...

然后结果将等于:

long multiplesSum(long N, long d) {
    long highestMultiple = (N-1) / d * d;
    long numberOfMultiples = highestMultiple / d;
    return (d + highestMultiple) * numberOfMultiples / 2;
}

我们需要减去long resultSum(long N) { return multiplesSum(N, 3) + multiplesSum(N, 5) - multiplesSum(N, 3*5); } ,因为有些数字是multiplesSum(N, 15)3的倍数,我们将它们加了两次。

复杂性: O(1)

答案 1 :(得分:0)

在这种情况下,您无法减少时间复杂度,因为每组数字仍有O(N)。但是,您可以使用整数除法来减少常数乘数

static int findMultiples(int N, int s)
{
    int c = N / s, sum = 0;
    for (int i = 0, k = s; i < c; i++, k += s)
        sum += k;
    return sum;
}

这样你只能循环遍历倍数而不是整个范围[0,N]。

请注意,您需要执行findMultiples(N, 3) + findMultiples(N, 5) - findMultiples(N, 15),以删除3和5的重复倍数。因此,循环次数为N / 3 + N / 5 + N / 15 = 0.6N而不是N

编辑:一般来说,任意数量的除数的解是sum(findMultiples(N,divisor_i) - findMultiples(N,LCM(all_divisors));但是,如果sum(1/divisor_i) + 1/LCM(all_divisors) < 1只是值得这样做,否则会有更多的循环。幸运的是,对于2个除数,这永远不会成真。

答案 2 :(得分:0)

从1到(包括)N的所有数字的总和已知为N(N + 1)/ 2(不需要迭代)。

因此,从K到KM的所有K的倍数之和是上述公式的K倍,得到KM(M + 1)/ 2.

将它与@meowgoesthedog的findMultiples(N,3)+ findMultiples(N,5) - findMultiples(N,15)想法相结合,你就有了一个恒定时间的解决方案。

答案 3 :(得分:-1)

解决问题的方法。解决问题的最快方法。

import java.util.*;
class Solution {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        while(t!=0)
        {
            long a=in.nextLong();
            long q=a-1;
            long aa=q/3;
            long bb=q/5;
            long cc=q/15;
            long aaa=((aa*(aa+1))/2)*3;
            long bbb=((bb*(bb+1))/2)*5;
            long ccc=((cc*(cc+1))/2)*15;
            System.out.println(aaa+bbb-ccc);
         t-=1;}
    }
}