Оптимизация времени работы алгоритма
Я пытаюсь найти способ оптимизировать свой алгоритм так, чтобы время работы было 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
индекс reachmax
тогда нет решения.
вы можете обратиться к этой вопрос/ответ для больше деталей и доказательства.
сложность времени для общего решения O(n²)
:
- сортировка массива:
O(nlogn)
. - итерация по отсортированному массиву:
O(n)
. - найдите два числа, которые суммируют значение:
O(n)
.
Итак,O(n²)
из-за вложенных вызовов FindTwoThatSumN
.
если вы хотите, вы можете передать индекс вместо числа в FindTwoThatSumN
метод, чтобы избежать дополнительной проверки, используйте сам номер как часть решения.
- вычислите все возможные суммы s+t и поместите результаты в набор => O (n2)
- повторите каждый r и проверьте, есть ли сумма, которая соответствует r => O (n) с
set.contains
бежит в постоянное время.