Самый большой простой множитель числа в Java

Я пытаюсь найти наибольший простой делитель числа, решая эту задачу здесь . Я думаю, что все делаю правильно, однако один из тестовых случаев (#2) дает сбой, и я не могу придумать ни одного крайнего случая, в котором он мог бы дать сбой. Вот мой код, пожалуйста, посмотрите и попробуйте что-нибудь найти.

public class ProblemThree
{
    public static void main(String[] args)
    {
        Scanner scanner = new Scanner(System.in);
        int T = scanner.nextInt();
        for (int i = 0; i < T; i++)
        {
            System.out.println(largestPrime(scanner.nextLong()));
        }
    }

    private static long largestPrime(long n)
    {
        while (n % 2 == 0)
        {
            n = n / 2;  // remove all the multiples of 2
        }
        while (n % 3 == 0)
        {
            n = n / 3; // remove all the multiples of 2
        }

        // remove multiples of prime numbers other than 2 and 3
        while (n >= 5)
        {
            boolean isDivisionComplete = true;
            for (long i = 5; i < Math.ceil(Math.sqrt(n)); i++)
            {
                if (n % i == 0)
                {
                    n = n / i;
                    isDivisionComplete = false;
                    break;
                }
            }
            if (isDivisionComplete)
            {
                break;
            }
        }
        return n;
    }
}

В основном, что я делаю, это:

Largest_Prime(n):
1. Repeatedly divide the no by any small number, say x where 0 < x < sqrt(n).
2. Then set n = n/x and repeat steps 1 and 2 until there is no such x that divides n.
3  Return n.

person OneMoreError    schedule 18.12.2015    source источник
comment
Подсказка: ваш код предполагает, что наибольший простой делитель 4 равен 1.   -  person OldCurmudgeon    schedule 18.12.2015


Ответы (5)


Кажется, у вас есть ошибка в вашем коде, например, когда вы вводите 16 largestPrime, функция возвращает 1. И это верно для случая, когда ввод представляет собой степень числа 3.

person Abu Hanifa    schedule 18.12.2015

Подробное описание алгоритма: Вы можете сделать это, сохраняя три переменные: Число, которое вы пытаетесь разложить на множители (A) Текущее хранилище делителей (B) Наибольшее хранилище делителей (C) Первоначально пусть (A) будет числом, которое вас интересует. - в данном случае это 600851475143. Тогда пусть (B) равно 2. Имеем условие, проверяющее, делится ли (A) на (B). Если оно делится, разделите (A) на (B), сбросьте (B) на 2 и вернитесь к проверке, делится ли (A) на (B). В противном случае, если (A) не делится на (B), увеличьте (B) на +1, а затем проверьте, делится ли (A) на (B). Запускайте цикл до тех пор, пока (A) не станет равным 1. Возвращаемое вами (3) будет наибольшим простым делителем числа 600851475143.

 public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int t = in.nextInt();
    for(int a0 = 0; a0 < t; a0++){
        long n = in.nextLong();
        long A=n;
        long B=2;
        long C=0;
        while(Math.pow(B,2)<=A)
            {
            if(A%B==0)
                {
                C=B;
                A=A/B;
                B=2;
            }
            else
               B++;

        }
           if(A>=C)
            C=A;
           if(A==1)
               { C=2;
                break;
               }
         System.out.println(C);   
    }
}
person Shree Prakash    schedule 22.10.2016
comment
пожалуйста, постарайтесь не давать только кодовые ответы. Было бы хорошо, если бы вы могли объяснить, что вы пытаетесь показать, или решаете ли вы какой-то конкретный вопрос в задаче. - person Pratik Bhattacharya; 22.10.2016
comment
Большое спасибо . Я написал подробности, связанные с Solution. - person Shree Prakash; 22.10.2016
comment
@Shree Ваше решение - полная помощь. - person Vinod; 22.10.2016

Почему вы удаляете кратные 2 и кратные 3? Таким образом, если у вас есть число, представляющее собой любую комбинацию степеней 2 и 3, вы получите ответ как 1, что явно неверно.

Для этой задачи вы можете сделать наивный способ зацикливания от 2 до sqrt (n) и сохранить наибольшее число, которое делит n, когда вы закончите свой цикл, просто верните наибольший найденный делитель.

person hbejgel    schedule 18.12.2015

1 сбросьте петлю для 2 и 3. Если нет, вы не получите 2, 2x2, 3, 2x3, ... все кратные 2 и 3

2 измените свой цикл, чтобы остановиться на 2 (а не на 5):

while (n >= 2)
{

3 остановись, если 2

if (n==2) return 2;

4 петля из 2

а также

5 цикл до sqrt(n), с ‹= и не только ‹ (если нет, вы не получите Prime X Prime)

for (long i = 2; i <= Math.ceil(Math.sqrt(n)); i++)
person guillaume girod-vitouchkina    schedule 18.12.2015

Один из простых способов извлечения простых множителей выглядит следующим образом:

/**
 * Prime factors of the number - not the most efficient but it works.
 *
 * @param n - The number to factorise.
 * @param unique - Want only unique factors.
 * @return - List of all prime factors of n.
 */
public static List<Long> primeFactors(long n, boolean unique) {
  Collection<Long> factors;
  if (unique) {
    factors = new HashSet<>();
  } else {
    factors = new ArrayList<>();
  }
  for (long i = 2; i <= n / i; i++) {
    while (n % i == 0) {
      factors.add(i);
      n /= i;
    }
  }
  if (n > 1) {
    factors.add(n);
  }
  return new ArrayList<>(factors);
}

Эти первые петли - проблема. Они сократят все четные числа до 1, таким образом, 2 не будет использоваться в качестве множителя. Изменение кода для использования:

while (n > 2 && n % 2 == 0) {
  n = n / 2;  // remove all the multiples of 2
}
while (n > 3 && n % 3 == 0) {
  n = n / 3; // remove all the multiples of 2
}

У вас все еще есть проблемы - например. вы сообщаете, что наибольший простой делитель числа 25 равен 25, а наибольший простой делитель числа 49 равен 49.

Просто запустите этот код, используя свой и мой, чтобы увидеть, где ваш не работает:

for (long i = 1; i < 1000; i++) {
  long largestPrime = largestPrime(i);

  List<Long> primeFactors = primeFactors(i, true);
  if (primeFactors.size() > 0) {
    Collections.sort(primeFactors, Collections.reverseOrder());
    long highestFactor = primeFactors.get(0);
    if (largestPrime != highestFactor) {
      System.out.println("Wrong! " + i + " " + largestPrime + " != " + primeFactors);
    }
  } else {
    System.out.println("No factors for " + i);
  }
}
person OldCurmudgeon    schedule 18.12.2015
comment
Парень просит помощи в исправлении его кода, и вы отвечаете на него, как если бы это был вопрос напишите мой код для меня, дублируя код еще один ответ? - person Didier L; 18.12.2015
comment
@DidierL - Это доска для профессионалов - я предлагаю профессиональное решение проблемы Самый большой простой делитель числа в Java. - person OldCurmudgeon; 18.12.2015
comment
Тогда почему бы вам просто не закрыть вопрос как дубликат любого другого вопроса, который задает то же самое? - person Didier L; 18.12.2015