Как сделать внутренний цикл for более эффективным?

#java

#java

Вопрос:

Я новичок в Java, и есть один вопрос, который заставляет меня задуматься. Как сделать внутренний цикл for более эффективным в этом коде?

     for (int i = 2; i <= 100; i  ) {
        System.out.print("Factors of "   i   " is: ");
        for (int j = 2; j < i; j  ) {
            if (i % j == 0)  System.out.print(j   " ");
        }
        System.out.println();
    }
  

Я просто пытался получить множители чисел от 2 до 100, но как я могу сделать внутренний цикл более эффективным?

Комментарии:

1. Для начала начните j с i/2 и уменьшайте его до j>1

Ответ №1:

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

 for (int i = 2; i <= 100; i  ) {
    System.out.print("Factors of "   i   " is: ");
    for (int j = 2; j <= (int) Math.sqrt(i); j  ) {
        if (i % j == 0)  System.out.print(j   " "   i / j   " ");
    }
    System.out.println();
}
  

Комментарии:

1. Разве вам не нужно также печатать i / j? Если 2 часто является фактором 100, i / j = 50 также является фактором. Также не должен ли цикл выполняться до тех пор, пока j <= (int) … ?

Ответ №2:

Вы могли бы использовать тот факт, что для каждого делителя a i существует такое число b , что a * b = i .

Найдите все делители a <= sqrt(i) , сохраните b = i/a и распечатайте эти значения позже.

 final int num = 100;
int[] divisors = new int[(int) Math.sqrt(num)];
for (int i = 2; i <= num; i  ) {
    System.out.print("Factors of "   i   " is: ");
    int j = 2;
    int index = 0;
    for (; j * j < i; j  ) {
        if (i % j == 0) {
            System.out.print(j   " ");
            divisors[index  ] = i / j;
        }
    }
    if (j * j == i) {
        // print sqrt(i) only once, if it's integral
        System.out.print(j   " ");
    }
    while (--index >= 0) {
        System.out.print(divisors[index]   " ");
    }
    System.out.println();
}
  

Таким образом, вашему внутреннему циклу нужны только O(sqrt(i)) O(i) операции вместо.

Ответ №3:

Эта временная сложность кода O(N2) .

  public static void main(String[] args) {

        for (int i = 2; i <= 100; i  ) {
        System.out.print("Factors of "   i   " is: ");
        for (int j = i/2; j > 1; j--) {
            if (i % j == 0)  System.out.print(j   " ");
        }
        System.out.println();
    }

  }
  

Попробуйте это, так как вывод вашего кода будет отображаться следующим образом (в порядке возрастания)

 Factors of 24 is: 2 3 4 6 8 12 
  

обратите внимание, но данный код будет отображаться следующим образом (в порядке убывания)

 Factors of 24 is: 12 8 6 4 3 2 
  

Комментарии:

1. Сложность от этого не меняется. O(1 2 ... n) = O(n²) = O(1 2 ... n/2) . Кроме того, это изменяет порядок делителей и выводит их в порядке убывания вместо возрастания.

2. да, оба являются внутренними циклами, поэтому временная сложность не изменится, @fabian я принимаю ваш комментарий 🙂

3. Вы не делаете его более эффективным, как просил спрашивающий!