Проект Euler #1 на Java
У меня проблемы с этим кодом. Я не хочу смотреть на других, поэтому мне интересно, что не так с моей.
Если мы перечислим все натуральные числа ниже 10, кратные 3 или 5, мы получим 3, 5, 6 и 9. Сумма этих кратных равна 23.
Найти сумму всех кратных 3 или 5 ниже 1000.
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 ответов
Решения
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
(1000) значения для i
во втором случае мы имеем только около n/3 + n/5 + n/15
(600) значения для i
, Второй также лучше, потому что меньше сравнений (нет 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 мс).
Ты должен сделать:
for (int i = 0; i < 1000; i++) {
if (i % 3 == 0 || i % 5 ==0) {
temp += i;
}
}
Это добавит каждый номер только один раз. В своем коде вы добавите 15 дважды, поскольку в обоих циклах это будет выполнено в обоих условиях.
Также обратите внимание, что в соответствии с требованиями, вы должны вернуться к < 1000
не <=
,
Если число является множителем как 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, так и для 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);
}
Ваш код неверен из-за простой проблемы: есть числа, которые можно разделить на 3 и 5. В вашем коде вы учитываете их дважды: один раз в первом цикле и во втором во втором цикле. Что вы должны сделать, это один из вариантов ниже:
О. Просто запустите один цикл и используйте два условия вместо одного: проверьте, можно ли разделить число на 3, а также можно разделить на 5 - и только затем добавьте его к общей сумме.
Б. Я создал код 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
Просто напишите этот простой код 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
Вы добавили все кратные 15 дважды. Используя ваш алгоритм, запустите третий цикл и проверьте, делится ли число на 15, а затем удалите его из общей суммы.
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);