Алгоритмическая сложность наивного кода для обработки всех последовательных подпоследовательностей списка: n ^ 2 или n ^ 3?

Я готовлюсь к тесту и нашел этот вопрос:

Я не могу определить сложность, я решил, что это либо O (n 2 ), либо O (n 3 ), и я склоняюсь к O (n 3 ).
Может кто-нибудь сказать мне, что это такое и почему?

Моя идея, что это O (n 2 ), заключается в том, что в цикле j, j = i, который дает форму треугольника, и затем петля k переходит от i + 1 к j, который, я думаю, является другой половиной треугольника.

public static int what(int[] arr)
{
    int m = arr[0];
    for (int i=0; i<arr.length; i++)
    {
        for (int j=i; j<arr.length;j++)
        {
            int s = arr[i];
            for (int k=i+1; k<=j; k++)
             s += arr[k];
            if (s > m)
             m = s;
        }
    }
    return m;
}

Кроме того, если вы можете сказать мне, что он делает?

Я полагал, что он возвращает добавление натуральных чисел или самого большого целого числа в массиве.
Но для массивов, таких как {99, -3, 0, 1}, возвращается 99, что, я думаю, связано с ошибками. Если нет, то я понятия не имею, что он делает:

{99, 1} => returns 100
{-1, -2, -3} => return -1
{-1, 5, -2} => returns 5
{99, -3, 0, 1} => returns 99 ???
29
задан 18.05.2020, 17:22

9 ответов

Вы можете продолжить методично, используя сигма-нотацию, чтобы получить порядок сложности роста:

enter image description here

49
ответ дан 18.05.2020, 17:23
  • 1
    Для опции 1 я добираюсь: Class 'App\Http\Controllers\View' not found – Kokodoko 10.03.2019, 00:22
  • 2
    +1, И это то, почему I' m печальный, что многие университеты отбрасывают требование инженерной математики для градуса CS... – Mysticial 18.05.2020, 17:23
  • 3
    Я вышел майор EE+CS. Таким образом, я должен был пройти всю высшую математику, которой ни один из моих приятелей только для CS не должен был даже касаться... В то время как я haven' t сохранил большую часть той математики, I' m довольный я все еще изучил его в какой-то момент. По крайней мере, я знаю, где посмотреть, когда мне нужен он. – Mysticial 18.05.2020, 17:24
  • 4
    Ну, я приложил персональное усилие, чтобы повторно завоевать математику через конкретные случаи (область алгоритмов). Однако мне была нужна методология, и я столкнулся с некоторыми документами, которые увеличили мое любопытство о Нотации Сигмы. Mark Allen Weiss' s Структуры данных и Аналитическая Книга Алгоритма (3-й выпуск), в Главе 1 или 2 (Максимальная проблема Подпоследовательности): случай с несколькими сигмами. Эти документы были очень полезны также: Jauhar и Nels – Mohamed Ennahdi El Idrissi 18.05.2020, 17:24
  • 5
    I' ve перепроверил это вниз к предпоследней строке (в котором точка эти O(n^3) уже ясно определяется), и я также подтверждаю there' s никакие ошибки! It' s интересный отметить, что постоянный множитель перед соответствующим n^3 термин 1/12, в противоположность типичному 1/2 для O(n^2) алгоритм, который формирует каждую возможную пару из последовательности и выполняет вычисление на паре. Т.е. третья сумма в OP' s вопрос - от i до j - вводит добавленное 1/6 к постоянному множителю, подразумевая, что эта подпоследовательность является [в среднем 118] ' th длина последовательности. – Dan Nissenbaum 18.05.2020, 17:25

У вас есть 3 для заявлений. Для больших n вполне очевидно, что это O(n^3). i и j имеют O(n) каждый, k немного короче, но все же O(n).

Алгоритм возвращает наибольшую сумму последовательных членов. Вот почему для последнего возвращается 99, даже если у вас есть 0 и 1, у вас также есть -3, который уменьшит вашу сумму до 97.

PS: треугольная форма означает 1 + 2 + ... + n = n(n+1) / 2 = O(n^2)

15
ответ дан 18.05.2020, 17:23
  • 1
    плюс, it' s окончательное решение для переменные использовали на нескольких occasionson 503 страницы после artisan down. Введение app' s строка версии как параметр объездчика лошадей кэша или отображение его в нижнем колонтитуле, пока обновление является тяжелой работой с другими решениями. (использование огибающей переменной для этого, вероятно, было бы самым чистым решением хотя), – luchaos 31.03.2016, 11:36
  • 2
    нет я проверил {-1,5,3,-2,2} < - Вы правы, что это возвращается 8 (последовательный). но тогда я проверил {-1,5,3,-2,2,1} < - теперь это возвращается 9, самый большой последовательный все еще 8 нет? – Seth Keno 18.05.2020, 17:24
  • 3
    Нет, 9 корректно. Это выберет 5, 3,-2, 2 и 1. Это doesn' t должны запуститься с начала. – Silviu Burcea 18.05.2020, 17:24

Независимо от формы треугольника или нет, это всегда сложность O (N ^ 3), но, конечно, с более низкой постоянной, чем полные тройные вложенные циклы.

3
ответ дан 18.05.2020, 17:24
  • 1
    Я думаю, что основное различие - то, что пользователь спрашивает относительно того, как иметь глобальный переменная, доступная во всех шаблонах. С принятым решением пользователь должен не забыть расширять родитель вызова и BaseController:: создайте и с решением ViewComposer он должен назвать Представление:: компоновщики в каждом контроллере создают метод для предоставления доступа к переменным доступными. – Nic Gutierrez 24.08.2016, 00:37

О (п ^ 3).

Вы вычислили любые два элемента между arr [0] и arr [arr.length - 1] , используя «i» и «j», что означает C (n, 2), что это n * (n + 1) / 2 раза расчета.

И средний шаг между каждым расчетом, выполняемым с помощью «k», составляет (0 + длина стрелки) / 2, поэтому общее время расчета составляет C (n, 2) * обр. длина / 2 = n * n * (n + 1) / 4, то есть O (n ^ 3).

3
ответ дан 18.05.2020, 17:24
  • 1
    @Wildling, Таким образом, Вы использовали КОНФИГУРАЦИЮ + = C++ 11 и Вы получили C++ 11 проблем компиляции? – Calaf 27.10.2014, 02:23

Код:

for (int i=0; i<arr.length; i++) // Loop A
{
    for (int j=i; j<arr.length;j++) // Loop B
    {
        for (int k=i+1; k<=j; k++) // Loop C
        {
            // ..
        }
    }
}

Асимптотический анализ на Big-O:

Loop A: Time = 1 + 1 + 1 + .. 1 (n times) = n

Loop B+C: Time = 1 + 2 + 3 + .. + m = m(m+1)/2

Time = SUM { m(m+1)/2 | m in (n,0] }

Time < n * (n(n+1)/2) = 1/2 n^2 * (n+1) = 1/2 n^3 + 1/2 n^2

Time ~ O(n^3)
9
ответ дан 18.05.2020, 17:25
  • 1
    это - лучшее решение, чем утвержденный ответ – Christophvh 13.08.2016, 02:17
  • 2
    Это не действительно корректно. B+C не является n (n+1)/2, потому что j запускается с меня. Не вычисляя результат, я думаю, что n (n-1) / 2 более точен. Конечно, с точки зрения большого, о, это не важно. – Silviu Burcea 18.05.2020, 17:26
  • 3
    @SilviuBurcea я использовал верхнюю границу, зафиксированное сообщение:) – Khaled.K 18.05.2020, 17:26

Полные рассуждения таковы:

Пусть n будет длиной массива.

1) Есть три вложенных цикла.

2) Самый внутренний цикл выполняет ровно j-i итераций (k, начиная с i+1 до j включительно). Нет преждевременного выхода из этого цикла.

3) Средний цикл выполняет ровно n-j итераций (j от i до n-1 включительно), каждая из которых включает j-i самых внутренних итераций, всего (i-i)+(i+1-i)+(i+2-i)+... (n-1-i) = 0+1+2... + (n-1-i). Нет преждевременного выхода из этого цикла.

4) Самый внешний цикл выполняет ровно n итераций (i работает от 0 до n-1 включительно), каждая из которых включает 0+1+2+ ... (n-1-i) внутренних итераций. Всего (0+1+2... n-1) + (0+1+2+... n-2) + (0+1+2+... n-3) + ... (0). Нет преждевременного выхода из этого цикла.

Теперь, как справиться с этим беспорядком? Вам нужно немного узнать о формуле Фолхабера ( http://en.wikipedia.org/wiki/Faulhaber%27s_formula ). В двух словах, он говорит, что сумма целых чисел до n равна O(n^2); и сумма суммы целых чисел до n равна O(n^3) и т. д.

Если вы помните из исчисления, примитив X является X^2/2; и примитивом X^2 является X^3/3. Каждый раз, когда степень увеличивается. Это не случайно.

Ваш код работает в O(n^3).

2
ответ дан 18.05.2020, 17:26
  • 1
    Да человек. Я обошел его при помощи CXXFLAGS – Chani 27.10.2014, 02:24

Вы можете смоделировать время работы функции как

sum(sum(sum(Theta(1), k=i+1..j),j=i..n),i=1..n)

Как

sum(sum(sum(1, k=i+1..j),j=i..n),i=1..n) = 1/6 n^3  - 1/6 n,

время работы - Theta (n ^ 3).

3
ответ дан 18.05.2020, 17:26
  • 1
    Это должно быть выбрано в качестве ответа! – lewis4u 27.10.2016, 21:32

Если вы недостаточно разбираетесь в основной теории, чтобы напрямую применять анализ @ MohamedEnnahdiElIdri, почему бы просто не начать с тестирования кода?

Обратите внимание, что границы цикла зависят только от длины массива. , а не его содержание, поэтому в отношении сложности времени не имеет значения, что делает алгоритм. Вы могли бы также проанализировать временную сложность

public static long countwhat(int length) {
  long count = 0;
  for (int i = 0; i < length; i++) {
    for (int j = i; j < length; j++) {
      for (int k = i + 1; k <= j; k++) {
        count++;
      }
    }
  }
  return count;
}

Глядя на это, легче ли вывести гипотезу? Если нет, просто проверьте, пропорционально ли возвращаемое значение length в квадрате или length в кубе ...

public static void main(String[] args) {
  for (int l = 1; l <= 10000; l *= 2) {
    long count = countwhat(l);
    System.out.println("i=" + l + ", #iterations:" + count + 
      ", #it/n²:" + (double) count / l / l +
      ", #it/n³:" + (double) count /  l / l / l);
  }
}

... и обратите внимание, что одно значение не приближается к какой-либо константе с ростом l, а другое (не случайно, к той же самой константе, связанной с наибольшей степенью $ n $ в методологическом анализе).

3
ответ дан 18.05.2020, 17:27
  • 1
    Различие между этим и view()->share - то, что это только выполняется, когда представление используется - но с view()->share it' s выполнил, неважно, что - Вы могли бы возвращать некоторый JSON в вызове API, например - который doesn' t используют представление. – Petecoop 03.03.2016, 01:54
  • 2
    Глупая идея. Сложность (чего-то вроде этого) не трудно выяснить, и тестирование маленьких значений n полностью в противоречии с математической идеей. – jwg 18.05.2020, 17:28
  • 3
    @jwg that' s смешной. Это - точно способ, которым Вы решаете математическую проблему, не, как Вы предполагаете, уже зная, как сделать это. Если бы Вы попросили, чтобы я нашел общую формулу как функцию номера n, я запустил бы путем разработки его для n = 1, 2, 3, 4, 5, 6; и если бы у меня был компьютер, то я мог бы пойти целых 10,000 и видеть, каково это. – djechlin 18.05.2020, 17:28
  • 4
    @djechlin И когда you' d закончил делать это, Вы могли начать использовать математику для нахождения ответа, который необходимо сделать так или иначе. – jwg 18.05.2020, 17:28
  • 5
    @jwg " не difficult" для Вас и меня, возможно. Но для OP? Почему они спрашивали, тогда? И " маленький values"? OP не спрашивает о некотором абстрактном алгоритме, но определенный метод, работающий на машине ограниченной памяти (фактический вход является международным массивом, возражайте против Вас). Кроме того, значения несомненно отбросят идею " треугольная форма, и затем [...] другая половина triangle" продвижение к O (n²). – arne.b 18.05.2020, 17:29
  • 6
    Почему они спрашивали? Хороший вопрос. Они спросили, потому что они учатся для теста (как указано в первой строке вопроса). Вопросом является осуществление. Очевидно это делает Ваше решение еще более глупым, чем если бы это была практическая проблема. – jwg 18.05.2020, 17:29

Это требует O(n^3) времени из-за того факта, что в трех циклах увеличиваются три различные переменные . То есть, когда один внутренний цикл закончен, это не влияет на внешний цикл. Внешний цикл выполняется столько раз, сколько он должен был работать до того, как был введен внутренний цикл.

И это проблема максимальной смежной суммы подмассивов. Самоочевиден, когда вы видите пример:

{99, 1} => returns 100
{-1, -2, -3} => return -1
{-1, 5, -2} => returns 5
{99, -3, 0, 1} => returns 99

Существует отличный алгоритм, известный как алгоритм Кадане (сделайте это для Google), который решает это за O(n) время.

Вот так:

Initialize:
    max_so_far = 0
    max_ending_here = 0

Loop for each element of the array
  (a) max_ending_here = max_ending_here + a[i]
  (b) if(max_ending_here < 0)
            max_ending_here = 0
  (c) if(max_so_far < max_ending_here)
            max_so_far = max_ending_here
return max_so_far

Ссылки: 1 , 2 , 3 .

3
ответ дан 18.05.2020, 17:28
  • 1
    Это не работает. Это все еще дает те же ошибки – Chani 25.10.2014, 23:30

Теги

Похожие вопросы