← Назад к вопросам
Проверка простого числа
1.0 Junior🔥 81 комментариев
#Другое#Основы Java
Условие
Напишите программу для определения, является ли число простым.
Простое число — натуральное число больше 1, которое делится только на 1 и на само себя.
Примеры
- 2 → простое
- 3 → простое
- 4 → не простое (делится на 2)
- 17 → простое
- 100 → не простое
Требования
- Базовый алгоритм за O(n)
- Оптимизированный алгоритм за O(√n)
- Обработайте числа <= 1
- Обработайте отрицательные числа
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Проверка простого числа
Это одна из базовых задач алгоритмики, которая позволяет демонстрировать понимание оптимизации и математических свойств. Рассмотрим несколько подходов от простого до оптимального.
Решение 1: Базовый алгоритм — O(n) время
Проверяем все числа от 2 до n-1:
public class PrimeCheckerBasic {
/**
* Базовый алгоритм проверки простого числа
* Время: O(n)
* Пространство: O(1)
*/
public static boolean isPrime(int n) {
// Обработка граничных случаев
if (n <= 1) {
return false; // числа <= 1 не являются простыми
}
if (n == 2) {
return true; // 2 — единственное четное простое число
}
if (n % 2 == 0) {
return false; // четные числа (кроме 2) не простые
}
// Проверяем делители от 3 до n-1
for (int i = 3; i < n; i += 2) { // проверяем только нечетные числа
if (n % i == 0) {
return false; // нашли делитель
}
}
return true; // простое число
}
public static void main(String[] args) {
System.out.println(isPrime(2)); // true
System.out.println(isPrime(3)); // true
System.out.println(isPrime(4)); // false
System.out.println(isPrime(17)); // true
System.out.println(isPrime(100)); // false
System.out.println(isPrime(1)); // false
System.out.println(isPrime(-5)); // false
}
}
Решение 2: Оптимизированный алгоритм — O(√n) время
Ключевое свойство: если n имеет делитель больший чем √n, то он должен иметь и делитель меньший чем √n. Поэтому нужно проверять только до √n:
public class PrimeCheckerOptimized {
/**
* Оптимизированный алгоритм проверки простого числа
* Время: O(√n)
* Пространство: O(1)
*/
public static boolean isPrime(int n) {
// Граничные случаи
if (n <= 1) {
return false;
}
if (n == 2) {
return true;
}
if (n % 2 == 0) {
return false;
}
// Проверяем делители от 3 до sqrt(n)
// Если число делится на число больше sqrt(n),
// то оно должно делиться и на число меньше sqrt(n)
int sqrt = (int) Math.sqrt(n);
for (int i = 3; i <= sqrt; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
public static void main(String[] args) {
System.out.println(isPrime(2)); // true
System.out.println(isPrime(3)); // true
System.out.println(isPrime(4)); // false
System.out.println(isPrime(17)); // true
System.out.println(isPrime(100)); // false
System.out.println(isPrime(97)); // true
System.out.println(isPrime(1000000007)); // true (большое простое число)
}
}
Решение 3: С дополнительной оптимизацией 6k±1
Все простые числа (кроме 2 и 3) имеют форму 6k±1. Это позволяет еще ускорить алгоритм:
public class PrimeCheckerAdvanced {
/**
* Продвинутая оптимизация: все простые числа имеют форму 6k±1
* Время: O(√n)
* Пространство: O(1)
*/
public static boolean isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return true; // 2 и 3 простые
if (n % 2 == 0 || n % 3 == 0) {
return false; // делится на 2 или 3
}
// Все простые числа имеют форму 6k-1 или 6k+1
int sqrt = (int) Math.sqrt(n);
for (int i = 5; i <= sqrt; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
}
Решение 4: С проверкой типов и обработкой особых случаев
public class PrimeCheckerRobust {
/**
* Надежная проверка с полной обработкой ошибок
*/
public static boolean isPrime(long n) {
// Отрицательные числа и числа <= 1
if (n <= 1) {
return false;
}
// Специальные случаи
if (n == 2 || n == 3) {
return true;
}
// Четные числа
if (n % 2 == 0) {
return false;
}
// Делится на 3
if (n % 3 == 0) {
return false;
}
// Проверяем делители вида 6k±1 до sqrt(n)
long sqrt = (long) Math.sqrt(n);
for (long i = 5; i <= sqrt; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
public static void main(String[] args) {
long[] testCases = {2, 3, 4, 5, 17, 100, -5, 0, 1, 1000000007L};
for (long num : testCases) {
System.out.printf("%d: %s%n", num, isPrime(num) ? "простое" : "не простое");
}
}
}
Для больших чисел: Тест Миллера-Рабина
Для очень больших чисел существуют вероятностные алгоритмы:
public class PrimeCheckerMillerRabin {
/**
* Тест Миллера-Рабина для больших чисел
* Вероятностный алгоритм
*/
public static boolean isPrime(long n, int iterations) {
if (n < 2) return false;
if (n == 2 || n == 3) return true;
if (n % 2 == 0) return false;
// Находим r и d такие что n-1 = 2^r * d
long d = n - 1;
int r = 0;
while (d % 2 == 0) {
d /= 2;
r++;
}
// Выполняем iterations раз
for (int i = 0; i < iterations; i++) {
long a = 2 + (long)(Math.random() * (n - 3));
long x = modPow(a, d, n);
if (x == 1 || x == n - 1) continue;
boolean composite = true;
for (int j = 0; j < r - 1; j++) {
x = (x * x) % n;
if (x == n - 1) {
composite = false;
break;
}
}
if (composite) return false;
}
return true;
}
private static long modPow(long base, long exp, long mod) {
long result = 1;
base %= mod;
while (exp > 0) {
if (exp % 2 == 1) {
result = (result * base) % mod;
}
base = (base * base) % mod;
exp /= 2;
}
return result;
}
}
Сравнение подходов
| Подход | Время | Применение |
|---|---|---|
| Базовый | O(n) | Обучение, малые числа |
| Оптимизированный | O(√n) | Стандартное решение |
| 6k±1 | O(√n) | Более быстро на практике |
| Миллер-Рабин | O(k log³ n) | Очень большие числа |
На собеседовании
- Начните с базового решения, объясните идею
- Оптимизируйте, показав, что проверка до √n достаточно
- Обсудите граничные случаи (1, 2, отрицательные числа)
- Упомяните более продвинутые методы для больших чисел
- Проверьте решение на примерах