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