60. Найти число, ближайшее к systemId
Условие задачи:
Метод getSystemSecretNumber() получает список чисел через NumberGenerator и должен вернуть число, ближайшее к systemId.
Расстояние между числами определяется как модуль их разности. Если два числа находятся на одинаковом расстоянии, возвращается первое встретившееся.
Код:
@Service
@RequiredArgsConstructor
public class ClosestNumberFinderService {
/*
* Бин подключается из библиотеки.
* Доступен только интерфейс:
*
* public interface NumberGenerator {
* List<Integer> loadNumbers();
* }
*/
private final NumberGenerator generator;
private final int systemId = 10;
public Integer getSystemSecretNumber() {
List<Integer> numbers = generator.loadNumbers();
return findClosestNumber(numbers, systemId);
}
private Integer findClosestNumber(
List<Integer> numbers,
int systemId
) {
// код тут
}
}
Примеры:
[3, 5, 7, 9, 12, 15], systemId = 10 → 9
[1, 8, 11, 20], systemId = 10 → 11
[10, 20, 30], systemId = 10 → 10
[-5, 0, 6], systemId = 4 → 6
Спойлеры к решению
Подсказки
💡 Храни ближайшее найденное число и минимальное расстояние.
💡 Для каждого элемента вычисляй модуль разности с
💡 Для расчёта расстояния используй
💡 Пустой список и
💡 Для каждого элемента вычисляй модуль разности с
systemId.💡 Для расчёта расстояния используй
long, чтобы избежать переполнения int.💡 Пустой список и
null нужно обработать отдельно.Решение
@Service
@RequiredArgsConstructor
public class ClosestNumberFinderService {
private final NumberGenerator generator;
private final int systemId = 10;
public Integer getSystemSecretNumber() {
List<Integer> numbers = generator.loadNumbers();
return findClosestNumber(numbers, systemId);
}
private Integer findClosestNumber(
List<Integer> numbers,
int systemId
) {
if (numbers == null || numbers.isEmpty()) {
throw new IllegalArgumentException(
"Numbers must not be empty"
);
}
Integer closestNumber = null;
long minimumDifference = Long.MAX_VALUE;
for (Integer number : numbers) {
if (number == null) {
continue;
}
long difference = Math.abs(
(long) number - systemId
);
if (difference < minimumDifference) {
minimumDifference = difference;
closestNumber = number;
}
}
if (closestNumber == null) {
throw new IllegalArgumentException(
"Numbers must contain at least one value"
);
}
return closestNumber;
}
}
Метод проходит по списку один раз и обновляет результат, когда находит число с меньшим расстоянием до systemId.
Строгое сравнение < сохраняет первое встретившееся число при одинаковом расстоянии.
Временная сложность — O(n), дополнительная память — O(1).