Оптимизация времени работы алгоритма

Я пытаюсь найти способ оптимизировать свой алгоритм так, чтобы время работы было O(n2) (Big O Notation).

входной сигнал массив с n элементами, только положительных и отрицательных целых чисел. Можно предположить, что массив уже отсортирован.

Я должен определить: для каждого r (элемента массива), является ли r = s + t, где s и t также являются элементами массива, и может быть одинаковым (s == t), или также нулевым.

Я попытался уменьшить количество элементы я должен проверить, проверяя, является ли текущее число положительным или отрицательным, но время работы все еще слишком долго. Проблема в том, что я использую 3 while loops, что уже означает время работы O(n3) для худшего случая.

вот мой код:

public static void Checker(int[] array) {
    List<Integer> testlist = new ArrayList<Integer>();
    int i = 0;
    while (i < array.length) {
        int current = array[i];
        if (attached(current, array)) {
            testlist.add(current);
        }
        i++;
    }
}

public static boolean attached(int current, int[] array) {
    boolean result = false;
    int i = 0;
    while (i < array.length && !result) {
        int number1 = array[i];
        int j = 0;
        while (j < array.length && !result) {
            int number2 = array[j];
            if (number1 + number2 == current) {
                result = true;
            }
            j++;
        }
        i++;
    }
    return result;
}

2 ответов


вы можете начать сортировку массива O(nlogn) (если нет), то для каждого элемента массива вы можете проверить, есть ли два элемента, сумма которых равна числу в O(n²).

код C#:

public static bool Solve(int[] arr)
{
    Array.Sort(arr);    //If not already sorted

    foreach (var num in arr)
        if (!FindTwoThatSumN(arr, num))
            return false;

    return true;
}

public static bool FindTwoThatSumN(int[] arr, int num)
{
    int min = 0;
    int max = arr.Length - 1;

    while (true)
    {
        if (min == max) break;

        int sum = arr[min] + arr[max];

        if (sum < num) min++;
        if (sum > num) max--;
        if (sum == num) return true;
    }

    return false;
}

идея проверить, есть ли два числа в массиве (должны быть отсортированы), что сумма определенного значения начинается с минимума (min = 0) и максимальное (max = arr.Length), затем в каждой итерации:

  • если сумма ниже, чем число, увеличить .
  • если сумма больше числа, уменьшите .
  • если сумма равна числу, то вы найдете решение.
  • если min индекс reach max тогда нет решения.

вы можете обратиться к этой вопрос/ответ для больше деталей и доказательства.

сложность времени для общего решения O(n²):

  • сортировка массива: O(nlogn).
  • итерация по отсортированному массиву:O(n).
  • найдите два числа, которые суммируют значение:O(n).

Итак,O(n²) из-за вложенных вызовов FindTwoThatSumN.

если вы хотите, вы можете передать индекс вместо числа в FindTwoThatSumN метод, чтобы избежать дополнительной проверки, используйте сам номер как часть решения.


  1. вычислите все возможные суммы s+t и поместите результаты в набор => O (n2)
  2. повторите каждый r и проверьте, есть ли сумма, которая соответствует r => O (n) с set.contains бежит в постоянное время.