我刚开始解决Project Eulers问题。尽管这个很简单。我想就最佳解决方案发表意见。
如果我们列出所有自然数字 10以下是3或5的倍数, 我们得到3,5,6和9.这些的总和 倍数是23。
求出3的所有倍数之和 或者低于1000。
这是我编码的方式:
package com.problem.one.ten;
public class NaturalNumber {
public static void main(String args[]) {
int sum=0;
for(int i=0; i<1000; i++) {
if((i%3 == 0) || (i%5 == 0)){
sum += i;
}
}
System.out.println(sum);
}
}
答案 0 :(得分:28)
更好的解决方案是包含 - 排除原则的简单应用。我们感兴趣的所有数字的总和是(1)可被3整除的所有数字的总和加上(2)可被5整除的所有数字的总和,减去(3)可被15整除的所有数字的总和。 3个和是算术级数的总和,相对容易找到。基本上,你不需要循环。
在 N 下面 n 可以整除的非负整数的数量正是[( N - 1)/ n < / em>] + 1.最大这样的数字是 n *([( N - 1)/ n ],因此算术进展和公式,它们的和是[( N - 1)/ n ] *([( N - 1)/ n ] + 1)* n / 2。
对于我们的案例,我们得到了:
最终结果是233168。
也许存在更好的解决方案。
答案 1 :(得分:11)
看起来不错,不过我会把sum
放在主页上。这对一个简单的程序来说并不是什么大不了的事。但一般来说,你应该在尽可能狭窄的范围内声明变量。
答案 2 :(得分:6)
虽然我确信这个问题有一个O(1)解决方案,但考虑到你只被要求提供1000的答案,找出它是不值得的。
我同意Matthew,sum应该是一个局部变量,但除此之外,你的代码对我来说也很好。
没有代码的解决方案(只是为了好玩):
使用sum(1+2+3+...+n)
= n(n+1)/2
这一事实,我们可以得出x低于1000的倍数之和为floor(1000/x)*(floor(1000/x)+1)/2*x
。
我们需要的答案是低于1000的3的倍数加上5的倍数之和减去15的倍数之和(否则将是双重数字)。
有999/3 = 333倍数3低于1000,999 / 5 = 199倍数5低于1000,而999/15 = 66倍数15低于1000
因此,所有3的倍数之和低于1000 = 333 * 334/2 * 3 = 166833,5的倍数之和低于1000 = 199 * 200/2 * 5 = 99500,以及15的倍数之和低于1000 = 66 * 67/2 * 15 = 33165
回答166833 + 99500 - 33165 = 233168
答案 3 :(得分:6)
您的解决方案在逻辑上最简单,因此最容易验证。像弗拉德和卢克这样的分析解决方案效率最高。
但是对于它的价值,当我看到问题时,我的第一个想法是:
public int doit()
{
int sum=0;
for (int n=0;n<1000;n+=3)
{
sum+=n;
}
for (int n=0;n<1000;n+=5)
{
if (n%3!=0) // Don't pick up the 3's twice
sum+=n;
}
return sum;
}
这比你的解决方案更有效率,因为它会跳过我们知道我们不感兴趣的数字。而且它的工作方式仍然非常明显。
无循环解决方案更好,但我发布这个只是因为我在5分钟内开会并且我已经在这里了。
答案 4 :(得分:3)
我使用O(1)的算术级数来做到这一点。这是我的解决方案,它适用于超过1000的值,直到10 ^ 9,如
long sum1=0,sum2=0,sum3=0,sum=0;
long no3=0,no5=0,no15=0;
//find the no of terms
no3=(array[i]-1)/3;
no5=(array[i]-1)/5;
no15=(array[i]-1)/15;
//find the sum of the terms
sum1=no3*(6+(no3-1)*3)/2 ;
sum2=no5*(10+(no5-1)*5)/2;
sum3=no15*(30+(no15-1)*15)/2;
sum=sum1+sum2-sum3;
System.out.println(sum);
}
答案 5 :(得分:2)
对于Project Euler,我有一个建议:去功能。
我以前在Java中已经解决了大约100个问题,但是我一直在努力解决很多问题,而且我不得不编写很多库代码。 我最近开始在Scala中解决它们,再次从问题1开始,感觉更自然。
除了你可以用笔和纸解决头几个问题之外,正如其他答案所指出的那样,使用函数式语言解决这个问题非常简单易行。 这是问题1的解决方案:
object Problem001 {
def main(args: Array[String]) = println(find(1000))
def find(max:Int) =
Stream.from(1) filter (n => n % 3 == 0 || n % 5 == 0) takeWhile (_ < max) sum
}
答案 6 :(得分:1)
弗拉德的解决方案规则 但是这里是另一个杰伊发布的内容,但是有一个循环
def ProjectEuler1(upper_limit):
num_3mult = (upper_limit-1)//3 # total multiples of 3, less than upper_limit
num_5mult = (upper_limit-1)//5 # total multiples of 5, less than upper_limit
sum_multiples = 0
for i in range(1,num_3mult+1):
sum_multiples += i*3
if i <= num_5mult and i%3!=0: # only add the multiples of 5 which are not multiple of 3 (to avoid adding duplicates)
sum_multiples += i*5
print('Sum of all multiples of 3 and 5 below 1000 = ', sum_multiples, end='\n')
ProjectEuler1(1000)
答案 7 :(得分:1)
我正在解决这个问题,并提出了@vlad提到的解决方案。非常激动(从未听说过包含 - 排除原则)。这是我的代码:
public class Prob1 {
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));
}
}
测试:
public class TestProb1 {
@Test
public void testSumOfMultiples(){
int actual = Prob1.sumOfMultiples(3, 5, 10);
assertEquals(23, actual);
actual = Prob1.sumOfMultiples(3, 5, 30);
assertEquals(195, actual);
actual = Prob1.sumOfMultiples(3, 5, 1000);
assertEquals(233168, actual);
}
}
答案 8 :(得分:0)
您可以使用单个LINQ表达式在.NET中解决此问题
Dim sum = (From num In Enumerable.Range(1, 999)
Where num Mod 3 = 0 OrElse num Mod 5 = 0
Select num).Sum()
答案 9 :(得分:0)
明显的算术系列是:
int s=0,n,N=1000;
n=(N-1)/ 3; s+= 3*n*(n+1);
n=(N-1)/ 5; s+= 5*n*(n+1);
n=(N-1)/15; s-=15*n*(n+1); s>>=1;
// can further optimize by precomputing N-1, n+1 to some temp vars
// also multiplication can be shift added instead
我在这里看到了一些suma fors以及为什么要成为那些人
试试这个:
int s=0,N=1000;
for (int i=0;i<N;i+=5) s+=i;
for (int i=0,j=0;i<N;i+=3,j++) if (j==5) j=0; else s+=i;
我知道这是微不足道的,但希望能帮助别人意识到如何更好地写作。
答案 10 :(得分:0)
我的第一个JAVA课程的第5周...这就是我如何解决它;)这是一个真正的凯旋门
import java.util.Scanner;
public class Counter {
public static void main(String args[]) {
System.out.println("Enter an integer, and COUNTER will find the sum of all the multiples of THREE and FIVE:");
int entry;
Scanner input = new Scanner(System.in);
entry = input.nextInt();
int three = 0;
int threeOut = 0;
int threeOpTot = (entry / 3);
int threeOp = 0;
while( threeOp < threeOpTot) {
three = three + 3 ;
threeOut = three + threeOut ;
threeOp += 1;
System.out.println(threeOp + " times 3 is " + three + ". ");
System.out.println(" " + threeOut + ", is the total sum of " + threeOp + "/" +
threeOpTot + " threes");
}
int five = 0;
int fiveOut = 0;
int fiveOpTot = (entry / 5);
int fiveOp = 1;
while( fiveOp < fiveOpTot) {
five = five + 5 ;
fiveOut = five + fiveOut ;
fiveOp += 1 ;
System.out.println(threeOp + " times 3 is " + three + ". ");
System.out.println(" " + threeOut + ", is the total sum of " +
threeOp + "/" + threeOpTot + " threes");
}
int fifteen = 0;
int fifteenOut = 0;
int fifteenOpTot = (entry / 15);
int fifteenOp = 0;
while( fifteenOp < fifteenOpTot) {
fifteen = fifteen + 15 ;
fifteenOut = fifteen + fifteenOut ;
fifteenOp += 1 ;
System.out.println(fifteenOp + " times fifteen is " + fifteen + ".");
System.out.println(" " + fifteenOut + ", is the total sum of " + fifteenOp +
"/" + fifteenOpTot + " fifteens");
}
System.out.println("The final values of threes' are " + (threeOut) );
System.out.println("The final values of five' are " + (fiveOut) );
System.out.println("The sum of the over-lapping 15 factors are " + (fifteenOut) );
System.out.println("Grand total: " + (fiveOut + threeOut - fifteenOut) );
}
}
答案 11 :(得分:0)
该算法可以正常工作,但您不认为它不是最佳算法。
这里找到 sum of n elements 的简单逻辑可以解决这个问题,而且这个算法也适用于大数据。
以下是我的博客CodeForWin - Project Euler 1: Multiples of 3 and 5
中程序的代码段n--; //Since we need to compute sum of multiples below n
if(n>=3) {
totalElements = n/3;
sum += (totalElements * ( 3 + totalElements*3)) / 2;
}
//Check if n is more than or equal to 5 then compute sum of all elements
//divisible by 5 and add to sum.
if(n >= 5) {
totalElements = n/5;
sum += (totalElements * (5 + totalElements * 5)) / 2;
}
//Check if n is more than or equal to 15 then compute sum of all elements
//divisible by 15 and subtract from sum.
if(n >= 15) {
totalElements = n/15;
sum -= (totalElements * (15 + totalElements * 15)) / 2;
}
System.out.println(sum);
此算法以毫秒为单位计算
sum
的{{1}}。
答案 12 :(得分:-1)
public static void main(String[] args) {
int sum = 0;
int i = 0;
while (i < 1000) {
if (i % 3 == 0 || i % 5 == 0) {
sum = sum + i;
}
i++;
}
System.out.println("Sum is " + sum);
}