Проходил собеседование сегодня, попалась задачка. Задачка странная, как для собеса, мне кажется, да и вообще оно странное какое-то было. То скоупы бинов спринга, то резко какая-то задачка, не особо в тему. Ну да ладно. Суть.
Есть последовательность от чего-то там до чего-то там. Нужно из этой последовательности дергать числа по какому-то условию и что-то там с ними делать.
Сигнатура и диапазон - из условий. Ну ок, элементарная задача.
Написал что-то такое, упомянув что можно это же сделать стримами.
/*
* Range 1-100
* Divisible by 3 - ....
* Divisible by 5 - ....
* Divisible by 3 and 5 - ....
* */
public void doWork() {
for (int i = 1; i <= 100; i++) {
if (i % 5 == 0 && i % 3 == 0) {
//
} else if (i % 5 == 0) {
//
} else if (i % 3 == 0) {
//
} else {
}
}
}
Далее, добавилось условие что вычисление остатка - ресурсоемкая операция. Сколько раз мол, в таком виде, она будет считаться? И как уменьшить количество вычислений?
Я ответил - 4 раза, в худшем случае. Как уменшить? Например сразу вычислить и положить в булеаны. Будет два вычисления - всегда.
public void doWork() {
for (int i = 1; i <= 100; i++) {
final boolean isDivisibleByThree = i % 3 == 0;
final boolean isDivisibleByFive = i % 5 == 0;
if (isDivisibleByFive && isDivisibleByThree) {
//
} else if (isDivisibleByFive) {
//
} else if (isDivisibleByThree) {
//
} else {
//
}
}
}
Можно со стороны математики зайти и вообще ничего не считать, как-то так. Грубо, но работает, вроде.
public void anotherDoWork() {
int byThree = 5;
int byFive = 3;
while (byFive <= 100) {
//do smth with byFive
//do smth with byThree
byThree += 3;
byFive += 5;
}
while (byThree <= 100) {
//do smth with byThree
byThree += 3;
}
}
Но, меня попросили найти еще способы.
К чему меня вели? Какие еще может кто придумать способы, кроме как пожертвовать памятью или найти более умный алгоритм? Делитесь идеями. У самого сегодня уже ничего в голову не лезет.