Java中的项目Euler#1

时间:2014-01-28 09:02:58

标签: java

我遇到了这段代码的问题。我不想看别人,所以我想知道我的错是什么。

如果我们列出10以下的所有自然数是3或5的倍数,我们得到3,5,6和9.这些倍数的总和是23.

查找低于1000的3或5的所有倍数的总和。

public class Multiples {
    public static void main (String [] args) {
        int temp = 0;
        int temp2 = 0; 

        for (int i = 0; i <= 1000; i++) {
            if (i % 3 == 0) {
                temp = temp + i;
            }            
        }

        for (int j = 0; j <= 1000; j++) {
            if (j % 5 == 0) {
                temp2 = temp2 + j;
            }
        }

        System.out.println(temp + temp2);
    }
}

我得到的值是267333,这是错误的。我的添加错了吗?我在算法上知道,这段代码可能达不到标准,但它应该有用,对吧?

8 个答案:

答案 0 :(得分:16)

解决方案

1)O(n):

其他答案的小改进(i可以从3开始):

public static void main(String[] args) {
    int sum = 0;
    for (int i = 3; i < 1000; i++) {
        if (i % 3 == 0 || i % 5 == 0) {
            sum += i;
        }
    }
    System.out.println(sum);
}

要获得更大的输入数字(Integer.MAX_VALUE而不是1000),需要:

  • 195秒

2)O(n)= O(n / 3)+ O(n / 5)+ O(n / 15):

效率更高并使用初始方法(删除两次拍摄的数字):

public static void main(String[] args) {
    long sum = 0 ;
    for ( long i = 3 ; i < 1000 ; i+=3 ){
        sum+=i;
    }
    for ( long i = 5 ; i < 1000 ; i+=5 ){
        sum+=i;
    }       
    for ( long i = 15 ; i < 1000 ; i+=15 ){
        sum-=i;
    }
    System.out.println(sum);
}

在第一种情况下,n的值大约为i(1000),在第二种情况下,n/3 + n/5 + n/15只有大约i(600)个值。第二个也更好,因为比较较少(不涉及if)。

要获得更大的输入数字(Integer.MAX_VALUE而不是1000),需要:

  • 9秒

3)O(1):

此解决方案基于以下观察:

  

1 + 2 + ... + n = n *(n + 1)/ 2

public static void main(String[] args) {
    int nr = 1000;
    nr--;
    int x3 = nr/3;
    int x5 = nr/5;
    int x15 = nr/15;

    long sum1 = 3*x3*(x3+1); 
    long sum2 = 5*x5*(x5+1);
    long sum3 = 15*x15*(x15+1);

    long sum = (sum1+sum2-sum3)/2;
    System.out.println(sum);
}

在这种情况下,即使输入为Integer.MAX_VALUE,计算速度也非常快(小于1毫秒)。

答案 1 :(得分:7)

你应该这样做:

for (int i = 0; i < 1000; i++) {
    if (i % 3 == 0 || i % 5 ==0) {
        temp += i;
    }
}

这将只添加一次每个数字。在你的代码中,你将添加两次15,因为它在两个循环中都会满足。

另请注意,根据要求,您应该循环到< 1000,而不是<=

答案 2 :(得分:1)

如果数字是3和5的乘数(例如:15,30,45等),您将计算两次。因此,不应该有两个for循环,而应该有一个具有复杂条件的循环:

public class Multiples {
    public static void main (String [] args) {
    int temp = 0;

    for (int i = 0; i < 1000; i++) {
        if (i % 3 == 0 || i % 5 == 0) {
            temp = temp + i;
        }

    }

    System.out.println (temp);
   }
}

答案 3 :(得分:0)

您添加了15的所有倍数两次。使用您的算法,运行第三个循环并测试该数字是否可被15整除,然后将其从总和中删除。

答案 4 :(得分:0)

由于一个简单的问题,您的代码不正确:有些数字也可以除以3和5。在您的代码中,您将它们计算两次:一次在第一个循环中,其次在第二个循环中。您应该做的是以下选项之一:

一个。只需运行一个循环并使用两个条件而不是一个:检查数字是否可以除以3,可以除以5 - 然后,然后将其添加到总和中。 / p>

B中。我使用了与您使用的相同的方法制作了一个Python代码,但是添加了条件。绝对不推荐也不高效,但它可以帮助您更好地理解。

numlist = []

for i in range (1, 1000):
    if i % 3 == 0:
        numlist.append(i)


for j in range (1, 1000):
    if j % 5 == 0:
        if not j in numlist:
            numlist.append(j)


counter = 0
for a in numlist:
    counter += a


print counter

答案 5 :(得分:0)

某些条件发生在两个条件满足3以及5的情况下。比如当i = 15满足15%3 == 0和15%5 == 0时。所以你的回答可能比预期的要多,因为你分别试过3和5。通过在这些特定条件下执行此操作,可以添加重复值。 因此,最好检查单循环。 像这样 -

    for(int i=0 ; i<1000 ; i++)
    {
        if(i%3==0 || i%5==0)
        {
            temp = temp + i;
        }
        System.out.println(temp);
    }

答案 6 :(得分:0)

只需编写这个简单的java代码。

 public static void main(String[] args)
{
int i,sum=0;
for ( i = 3; i <1000; i++)
 {
 if ((i % 3 == 0)||(i%5==0) )
 sum=sum+i;
 }
System.out.print(sum);
}

您将获得输出233168

答案 7 :(得分:-1)

public static int sumOfMultiples(int i, int j, int limit){
    int s = --limit / i, t = limit / j, u = limit / (i * j);
    return (i*(s*(s+1)/2)) + (j*(t*(t+1)/2)) - ((i*j)*(u*(u+1)/2));
}

测试

actual = Prob1.sumOfMultiples(3, 5, 1000);
assertEquals(233168, actual);