Java中的Euler程序

时间:2010-11-09 18:55:37

标签: java

我刚开始解决Project Eulers问题。尽管这个很简单。我想就最佳解决方案发表意见。

The problem

  

如果我们列出所有自然数字   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);
    }
}

13 个答案:

答案 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。

对于我们的案例,我们得到了:

  1. N = 1000, n = 3,[( N - 1)/ n ] = 333 ,sum = 333 * 334 * 3/2。
  2. N = 1000, n = 5,[( N - 1)/ n ] = 199 ,sum = 199 * 200 * 5/2。
  3. N = 1000, n = 15,[( N - 1)/ n ] = 66 ,sum = 66 * 67 * 15/2。
  4. 最终结果是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以及为什么要成为那些人

  • 使用suma ???
  • 对+ 3i和+ 5i乘数使用+1增量???

试试这个:

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