Java中的项目Euler#1

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

如果我们列出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,这是错误的。 我的添加错了吗? 我在算法上知道,这段代码可能达不到标准,但它应该有用,对吧?

解决方案

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

在第一种情况下,对于i ,我们有大约n (1000)个值,在第二种情况下,对于i ,我们只有大约n/3 + n/5 + n/15 (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 ms)。

你应该做:

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

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

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

如果数字是3和5的乘数(例如:15,30,45等),您将计算两次。 因此,您应该拥有一个具有复杂条件的for循环,而不是两个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); } } 

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

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

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

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 

某些条件发生在两个条件满足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); } 

只写这个简单的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

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