Предположим, что в данном n нет равных чисел, и разрешено использовать одно число более одного раза.Например, мы дали числа {1,2,3}, чтобы мы могли создать 7 треугольников:
- 1 1 1
- 1 2 2
- 13 3
- 2 2 2
- 2 2 3
- 2 3 3
- 3 3 3
Если какое-либо из этих предположений неверно, алгоритм легко изменить.
Здесь я представляю алгоритм, который в худшем случае занимает время O (n ^ 2):
- Сортировка номеров (в порядке возрастания).Мы возьмем тройки ai <= aj <= ak, так что i <= j <= k. </li>
- Для каждого i, j вам нужно найти наибольшее k, удовлетворяющее ak <= ai + aj.Тогда все тройки (ai, aj, al) j <= l <= k - треугольник (поскольку ak> = aj> = ai мы можем нарушать только ak
Рассмотрим две пары (i, j1) и (i, j2) j1 <= j2.Легко видеть, что k2 (найдено на шаге 2 для (i, j2))> = k1 (найдено один шаг 2 для (i, j1)).Это означает, что если вы выполняете итерацию для j, и вам нужно только проверять числа, начиная с предыдущего k.Таким образом, он дает вам O (n) сложность времени для каждого конкретного i, что подразумевает O (n ^ 2) для всего алгоритма.
Исходный код C ++:
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 во втором издании). Находить сложность путем подсчета вложенных циклов иногда совершенно неправильно. Здесь я пытаюсь объяснить это настолько просто, насколько смогу.Давайте исправим переменную i .Затем для этого i мы должны выполнить итерацию j с i до n (это означает операцию O (n)) и внутреннюю итерацию цикла k от i до n (это также означает операцию O (n)). Примечание: я не запускаю цикл с начала для каждого j .Нам также нужно сделать это для каждого i от 0 до n .Таким образом, это дает нам n * (O (n) + O (n)) = O (n ^ 2) .