Если указаны цифры n
, как бы найти общее количество возможных треугольников? Есть ли способ, который делает это менее чем за O(n^3)
?
Я рассматриваю условия a+b>c
, b+c>a
и a+c>b
для того, чтобы быть треугольником.
Если указаны цифры n
, как бы найти общее количество возможных треугольников? Есть ли способ, который делает это менее чем за O(n^3)
?
Я рассматриваю условия a+b>c
, b+c>a
и a+c>b
для того, чтобы быть треугольником.
Предположим, что в заданном n нет равных чисел, и ему разрешено использовать одно число более одного раза. Например, мы дали числа {1,2,3}, поэтому мы можем создать 7 треугольников:
Если какое-либо из этих предположений неверно, легко изменить алгоритм.
Здесь я представляю алгоритм, который берет O (n ^ 2) раз в худшем случае:
Рассмотрим две пары (i, j1) и (i, j2) j1 <= j2. Легко видеть, что k2 (найденный на шаге 2 для (i, j2)) >= k1 (найден один шаг 2 для (i, j1)). Это означает, что если вы итерации для j, и вам нужно только проверить числа, начиная с предыдущего k. Таким образом, это дает вам сложность времени O (n) для каждого конкретного i, что подразумевает O (n ^ 2) для всего алгоритма.
Исходный код С++:
int Solve(int* a, int n)
{
int answer = 0;
std::sort(a, a + n);
for (int i = 0; i < n; ++i)
{
int k = i;
for (int j = i; j < n; ++j)
{
while (n > k && a[i] + a[j] > a[k])
++k;
answer += k - j;
}
}
return answer;
}
Обновление для downvoters:
Это определенно O (n ^ 2)! Прочтите внимательно "Введение алгоритмов" в главе Томаса Х. Кормена "Амортизированный анализ" (17.2 во втором издании). Поиск сложности путем подсчета вложенных циклов иногда является неправильным. Здесь я стараюсь объяснить это как можно проще. Пусть fix я переменная. Тогда для этого я мы должны перебирать j из я в n (это означает, что O (n) операция), а внутренний while цикл итерации k от я до n (это также означает операцию O (n)). Примечание. Я не запускаю цикл с начала для каждого j. Нам также нужно сделать это для каждого я от 0 до n. Поэтому он дает нам n * (O (n) + O (n)) = O (n ^ 2).
Если вы используете двоичную сортировку, то O (n-log (n)), правильно? Держите свое двоичное дерево удобным и для каждой пары (a, b), где b и c < (А + б).
В O(n^2*logn)
есть простой алгоритм.
(a, b, c)
, где a <= b <= c
.a + b > c
(другие тогда тривиально).И теперь:
O(n * logn)
, например. by merge-sort.(a, b), a <= b
оставшееся значение c
должно быть не менее b
и меньше a + b
.[b, a+b)
.Это можно просто выполнить путем двоичного поиска этих двух значений (дважды O(logn)
, это создает два индекса) и подсчета количества элементов между ними.
Все вместе O(n * logn + n^2 * logn)
, которое O(n^2 * logn)
. Надеюсь, это поможет.
Я разработал алгоритм, который работает в O (n ^ 2 lgn) времени. Я думаю, что это правильно... Код написан на С++...
int Search_Closest(A,p,q,n) /*Returns the index of the element closest to n in array
A[p..q]*/
{
if(p<q)
{
int r = (p+q)/2;
if(n==A[r])
return r;
if(p==r)
return r;
if(n<A[r])
Search_Closest(A,p,r,n);
else
Search_Closest(A,r,q,n);
}
else
return p;
}
int no_of_triangles(A,p,q) /*Returns the no of triangles possible in A[p..q]*/
{
int sum = 0;
Quicksort(A,p,q); //Sorts the array A[p..q] in O(nlgn) expected case time
for(int i=p;i<=q;i++)
for(int j =i+1;j<=q;j++)
{
int c = A[i]+A[j];
int k = Search_Closest(A,j,q,c);
/* no of triangles formed with A[i] and A[j] as two sides is (k+1)-2 if A[k] is small or equal to c else its (k+1)-3. As index starts from zero we need to add 1 to the value*/
if(A[k]>c)
sum+=k-2;
else
sum+=k-1;
}
return sum;
}
Надеюсь, это поможет........
Хотя мы можем использовать бинарный поиск, чтобы найти значение "k", и, следовательно, улучшить временную сложность!
Пусть a, b и c - три стороны. Нижнее условие должно выполняться для треугольника (сумма двух сторон больше третьей)
i) a + b > c
ii) b + c > a
iii) a + c > b
Ниже приведены шаги для подсчета треугольника.
Сортировка массива в неубывающем порядке.
Инициализируйте два указателя "i" и "j" на первый и второй элементы соответственно и инициализируйте количество треугольников как 0.
Исправьте 'i и' j и найдите самый правый индекс 'k (или самый большой' arr [k] '), такой, что' arr [i] + arr [j] > arr [k] '. Число треугольников, которые могут быть сформированы с помощью "arr [i]" и "arr [j]" в виде двух сторон, равно "k - j. Добавьте 'k - j в число треугольников.
Рассмотрим 'arr [i]' как 'a,' arr [j] 'как b и все элементы между' arr [j + 1] 'и' arr [k] 'как' c. Вышеупомянутые условия (ii) и (iii) выполняются, потому что 'arr [i] arr [j] обр [к]. И мы проверяем условие (i), когда мы выбираем 'k'
4.Инкремент 'j снова зафиксирует второй элемент.
Обратите внимание, что на шаге 3 мы можем использовать предыдущее значение 'k. Причина проста, если мы знаем, что значение 'arr [i] + arr [j-1]' больше, чем 'arr [k]', то мы можем сказать: 'arr [i] + arr [j]' также будет больше, чем 'arr [k]', потому что массив сортируется в порядке возрастания.
5.If 'j достигло конца, затем увеличит' i. Инициализируйте 'j как' я + 1 ',' k как 'i + 2' и повторите шаги 3 и 4.
Сложность времени: O (n ^ 2). Сложность времени выглядит больше из-за 3 вложенных циклов. Если мы более подробно рассмотрим алгоритм, заметим, что k инициализируется только один раз в самом внешнем цикле. Самый внутренний цикл выполняет не более O (n) времени для каждой итерации внешнего большинства циклов, так как k начинается с я + 2 и идет до n для всех значений j. Следовательно, временная сложность O (n ^ 2).
N0,N1,N2,...Nn-1
sort
X0,X1,X2,...Xn-1 as X0>=X1>=X2>=...>=Xn-1
choice X0(to Xn-3) and choice form rest two item x1...
choice case of (X0,X1,X2)
check(X0<X1+X2)
OK is find and continue
NG is skip choice rest
Кажется, что алгоритм лучше, чем O (n ^ 3). В худшем случае сам результат имеет O (n ^ 3) элементов.
Например, если указано n равных чисел, алгоритм должен вернуть результаты n * (n-1) * (n-2).