This commit is contained in:
krahets
2026-03-30 08:17:41 +08:00
parent 68cafe99dd
commit 46bccf0065
484 changed files with 60193 additions and 20315 deletions
@@ -65,8 +65,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Noto Sans";--md-code-font:"JetBrains Mono"}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"PT Sans";--md-code-font:"JetBrains Mono"}</style>
@@ -574,7 +574,7 @@
<span class="md-ellipsis">
Глава 1. Знакомство с алгоритмами
Глава 1. Введение в алгоритмы
@@ -596,7 +596,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 1. Знакомство с алгоритмами
Глава 1. Введение в алгоритмы
</label>
@@ -646,7 +646,7 @@
<span class="md-ellipsis">
1.2 Что такое структуры данных и алгоритмы
1.2 Что такое алгоритм
@@ -1336,7 +1336,7 @@
<span class="md-ellipsis">
Глава 4. Массив и связный список
Глава 4. Массивы и списки
@@ -1358,7 +1358,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 4. Массив и связный список
Глава 4. Массивы и списки
</label>
@@ -1464,7 +1464,7 @@
<span class="md-ellipsis">
4.4 Память и кеш *
4.4 Оперативная память и кэш *
@@ -1746,7 +1746,7 @@
<span class="md-ellipsis">
Глава 6. Хеширование
Глава 6. Хеш-таблицы
@@ -1768,7 +1768,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 6. Хеширование
Глава 6. Хеш-таблицы
</label>
@@ -1846,7 +1846,7 @@
<span class="md-ellipsis">
6.3 Хеш-алгоритмы
6.3 Алгоритмы хеширования
@@ -1941,7 +1941,7 @@
<span class="md-ellipsis">
Глава 7. Дерево
Глава 7. Деревья
@@ -1963,7 +1963,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 7. Дерево
Глава 7. Деревья
</label>
@@ -2041,7 +2041,7 @@
<span class="md-ellipsis">
7.3 Представление дерева массивом
7.3 Представление двоичного дерева массивом
@@ -2125,7 +2125,7 @@
<span class="md-ellipsis">
7.6 Резюме
7.6 Краткие итоги
@@ -2288,7 +2288,7 @@
<span class="md-ellipsis">
8.3 Задача Top-K
8.3 Задача Top-k
@@ -2379,7 +2379,7 @@
<span class="md-ellipsis">
Глава 9. Граф
Глава 9. Графы
@@ -2401,7 +2401,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 9. Граф
Глава 9. Графы
</label>
@@ -2451,7 +2451,7 @@
<span class="md-ellipsis">
9.2 Базовые операции над графами
9.2 Базовые операции графа
@@ -2507,7 +2507,7 @@
<span class="md-ellipsis">
9.4 Резюме
9.4 Краткие итоги
@@ -2646,7 +2646,7 @@
<span class="md-ellipsis">
10.2 Точка вставки двоичного поиска
10.2 Двоичный поиск точки вставки
@@ -2674,7 +2674,7 @@
<span class="md-ellipsis">
10.3 Граничные случаи двоичного поиска
10.3 Двоичный поиск границ
@@ -2702,7 +2702,7 @@
<span class="md-ellipsis">
10.4 Стратегия оптимизации через хеширование
10.4 Стратегии оптимизации хеширования
@@ -2730,7 +2730,7 @@
<span class="md-ellipsis">
10.5 Алгоритмы поиска: новый взгляд
10.5 Переосмысление алгоритмов поиска
@@ -2935,7 +2935,7 @@
<span class="md-ellipsis">
11.3 Пузырьковая сортировка
11.3 Сортировка пузырьком
@@ -2963,7 +2963,7 @@
<span class="md-ellipsis">
11.4 Сортировка вставкой
11.4 Сортировка вставками
@@ -3268,7 +3268,7 @@
<span class="md-ellipsis">
12.1 Алгоритмы разделяй и властвуй
12.1 Стратегия разделяй и властвуй
@@ -3296,7 +3296,7 @@
<span class="md-ellipsis">
12.2 Стратегия поиска разделяй и властвуй
12.2 Поисковая стратегия разделяй и властвуй
@@ -3573,7 +3573,7 @@
<span class="md-ellipsis">
13.4 Задача о $n$ ферзях
13.4 Задача о n ферзях
@@ -3714,7 +3714,7 @@
<span class="md-ellipsis">
14.1 Введение в динамическое программирование
14.1 Первое знакомство с динамическим программированием
@@ -3826,7 +3826,7 @@
<span class="md-ellipsis">
14.5 Задача о неограниченном рюкзаке
14.5 Задача о полном рюкзаке
@@ -4521,26 +4521,26 @@
<!-- Page content -->
<h1 id="24">2.4 &nbsp; Пространственная сложность<a class="headerlink" href="#24" title="Permanent link">&para;</a></h1>
<p><u>Пространственная сложность (space complexity)</u> используется для оценки того, как меняется объем памяти, занимаемой алгоритмом, по мере роста объема данных. Это понятие очень похоже на временную сложность, только вместо "времени выполнения" мы рассматриваем "объем используемой памяти".</p>
<p><u>Пространственная сложность (space complexity)</u> служит для оценки того, как меняется объем памяти, требуемой алгоритму, по мере роста объема данных. Это понятие очень похоже на временную сложность, только вместо времени выполнения рассматривается объем используемой памяти.</p>
<h2 id="241">2.4.1 &nbsp; Пространство, связанное с алгоритмом<a class="headerlink" href="#241" title="Permanent link">&para;</a></h2>
<p>Память, которую использует алгоритм во время работы, в основном включает несколько следующих частей.</p>
<p>Память, которую использует алгоритм во время работы, в основном делится на следующие части.</p>
<ul>
<li><strong>Входное пространство</strong>: используется для хранения входных данных алгоритма.</li>
<li><strong>Временное пространство</strong>: используется для хранения переменных, объектов, контекста функций и других данных, возникающих во время выполнения алгоритма.</li>
<li><strong>Выходное пространство</strong>: используется для хранения выходных данных алгоритма.</li>
</ul>
<p>В общем случае при анализе пространственной сложности в расчет включают "временное пространство" и "выходное пространство".</p>
<p>Как правило, при анализе пространственной сложности в расчет включают временное пространство и выходное пространство.</p>
<p>Временное пространство можно дополнительно разделить на три части.</p>
<ul>
<li><strong>Временные данные</strong>: используются для хранения различных констант, переменных, объектов и т.д., возникающих во время выполнения алгоритма.</li>
<li><strong>Пространство кадров стека</strong>: используется для хранения контекстных данных вызываемых функций. Система при каждом вызове функции создает на вершине стека новый кадр; после возврата функции пространство этого кадра освобождается.</li>
<li><strong>Пространство кадров стека</strong>: используется для хранения контекстных данных вызываемых функций. При каждом вызове функции система создает на вершине стека новый кадр; после возврата функции пространство этого кадра освобождается.</li>
<li><strong>Пространство инструкций</strong>: используется для хранения скомпилированных инструкций программы и в реальном подсчете обычно не учитывается.</li>
</ul>
<p>При анализе пространственной сложности программы <strong>мы обычно учитываем три части: временные данные, пространство кадров стека и выходные данные</strong>, как показано на рисунке 2-15.</p>
<p>При анализе пространственной сложности программы <strong>обычно учитываются временные данные, пространство стека и выходные данные</strong>, как показано на рисунке 2-15.</p>
<p><img alt="Пространство, используемое алгоритмом" class="animation-figure" src="../space_complexity.assets/space_types.png" /></p>
<p align="center"> Рисунок 2-15 &nbsp; Пространство, используемое алгоритмом </p>
<p>Соответствующий код выглядит следующим образом:</p>
<p>Ниже приведен соответствующий код:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:13"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><input id="__tabbed_1_13" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Kotlin</label><label for="__tabbed_1_13">Ruby</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -4857,12 +4857,12 @@
</div>
</div>
<h2 id="242">2.4.2 &nbsp; Метод вывода<a class="headerlink" href="#242" title="Permanent link">&para;</a></h2>
<p>Метод вывода пространственной сложности в целом аналогичен временному анализу: меняется только объект подсчета, с "количества операций" на "размер используемого пространства".</p>
<p>В отличие от временной сложности, <strong>обычно мы рассматриваем только худшую пространственную сложность</strong>. Это связано с тем, что память является жестким ограничением: нам нужно гарантировать, что для любых входных данных у программы будет достаточно памяти.</p>
<p>Рассмотрим следующий код. Слово "худшая" в "худшей пространственной сложности" имеет два значения.</p>
<p>Метод вывода пространственной сложности в целом аналогичен выводу временной сложности: меняется только объект подсчета, с количества операций на размер используемого пространства.</p>
<p>В отличие от временной сложности, <strong>обычно рассматривается только худшая пространственная сложность</strong>. Это связано с тем, что память является жестким ограничением: необходимо гарантировать, что для любых входных данных у программы будет достаточно памяти.</p>
<p>Рассмотрим следующий код. Понятие худшей пространственной сложности здесь имеет два значения.</p>
<ol>
<li><strong>Ориентир на худшие входные данные</strong>: когда <span class="arithmatex">\(n &lt; 10\)</span> , пространственная сложность равна <span class="arithmatex">\(O(1)\)</span> ; но когда <span class="arithmatex">\(n &gt; 10\)</span> , инициализированный массив <code>nums</code> занимает <span class="arithmatex">\(O(n)\)</span> пространства, поэтому худшая пространственная сложность равна <span class="arithmatex">\(O(n)\)</span> .</li>
<li><strong>Ориентир на пиковое потребление памяти во время выполнения алгоритма</strong>: например, до выполнения последней строки программа занимает <span class="arithmatex">\(O(1)\)</span> пространства; при инициализации массива <code>nums</code> она занимает <span class="arithmatex">\(O(n)\)</span> пространства, поэтому худшая пространственная сложность равна <span class="arithmatex">\(O(n)\)</span> .</li>
<li><strong>Ориентир на пиковое использование памяти во время выполнения</strong>: например, до выполнения последней строки программа занимает <span class="arithmatex">\(O(1)\)</span> пространства; при инициализации массива <code>nums</code> она занимает <span class="arithmatex">\(O(n)\)</span> пространства, поэтому худшая пространственная сложность также равна <span class="arithmatex">\(O(n)\)</span> .</li>
</ol>
<div class="tabbed-set tabbed-alternate" data-tabs="2:13"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><input id="__tabbed_2_12" name="__tabbed_2" type="radio" /><input id="__tabbed_2_13" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Python</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Java</label><label for="__tabbed_2_4">C#</label><label for="__tabbed_2_5">Go</label><label for="__tabbed_2_6">Swift</label><label for="__tabbed_2_7">JS</label><label for="__tabbed_2_8">TS</label><label for="__tabbed_2_9">Dart</label><label for="__tabbed_2_10">Rust</label><label for="__tabbed_2_11">C</label><label for="__tabbed_2_12">Kotlin</label><label for="__tabbed_2_13">Ruby</label></div>
<div class="tabbed-content">
@@ -5248,7 +5248,7 @@
<li>Рекурсивная функция <code>recur()</code> во время выполнения одновременно содержит <span class="arithmatex">\(n\)</span> еще не завершившихся экземпляров <code>recur()</code> , поэтому занимает <span class="arithmatex">\(O(n)\)</span> пространства кадров стека.</li>
</ul>
<h2 id="243">2.4.3 &nbsp; Распространенные типы<a class="headerlink" href="#243" title="Permanent link">&para;</a></h2>
<p>Пусть размер входных данных равен <span class="arithmatex">\(n\)</span> . На рисунке 2-16 показаны распространенные типы пространственной сложности (в порядке от меньшей к большей).</p>
<p>Пусть размер входных данных равен <span class="arithmatex">\(n\)</span> . На рисунке 2-16 показаны распространенные типы пространственной сложности в порядке от меньшей к большей.</p>
<div class="arithmatex">\[
\begin{aligned}
O(1) &lt; O(\log n) &lt; O(n) &lt; O(n^2) &lt; O(2^n) \newline
@@ -5259,7 +5259,7 @@ O(1) &lt; O(\log n) &lt; O(n) &lt; O(n^2) &lt; O(2^n) \newline
<p align="center"> Рисунок 2-16 &nbsp; Распространенные типы пространственной сложности </p>
<h3 id="1-o1">1. &nbsp; Постоянная сложность <span class="arithmatex">\(O(1)\)</span><a class="headerlink" href="#1-o1" title="Permanent link">&para;</a></h3>
<p>Постоянная сложность часто встречается у констант, переменных и объектов, количество которых не зависит от размера входных данных <span class="arithmatex">\(n\)</span> .</p>
<p>Постоянная сложность обычно встречается у констант, переменных и объектов, количество которых не зависит от размера входных данных <span class="arithmatex">\(n\)</span> .</p>
<p>Следует заметить, что память, занятая инициализацией переменных или вызовом функций внутри цикла, освобождается при переходе к следующей итерации, поэтому она не накапливается, и пространственная сложность по-прежнему остается <span class="arithmatex">\(O(1)\)</span> :</p>
<div class="tabbed-set tabbed-alternate" data-tabs="4:13"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><input id="__tabbed_4_13" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Python</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Java</label><label for="__tabbed_4_4">C#</label><label for="__tabbed_4_5">Go</label><label for="__tabbed_4_6">Swift</label><label for="__tabbed_4_7">JS</label><label for="__tabbed_4_8">TS</label><label for="__tabbed_4_9">Dart</label><label for="__tabbed_4_10">Rust</label><label for="__tabbed_4_11">C</label><label for="__tabbed_4_12">Kotlin</label><label for="__tabbed_4_13">Ruby</label></div>
<div class="tabbed-content">
@@ -5595,7 +5595,7 @@ O(1) &lt; O(\log n) &lt; O(n) &lt; O(n^2) &lt; O(2^n) \newline
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=class%20ListNode%3A%0A%20%20%20%20%22%22%22%D0%9A%D0%BB%D0%B0%D1%81%D1%81%20%D1%83%D0%B7%D0%BB%D0%B0%20%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D0%B3%D0%BE%20%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0%22%22%22%0A%20%20%20%20def%20__init__%28self%2C%20val%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20self.val%3A%20int%20%3D%20val%20%20%23%20%D0%97%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%20%D1%83%D0%B7%D0%BB%D0%B0%0A%20%20%20%20%20%20%20%20self.next%3A%20ListNode%20%7C%20None%20%3D%20None%20%20%23%20%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D0%B0%20%D0%BD%D0%B0%20%D1%83%D0%B7%D0%B5%D0%BB-%D0%BF%D1%80%D0%B5%D0%B5%D0%BC%D0%BD%D0%B8%D0%BA%0A%0Adef%20function%28%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F%22%22%22%0A%20%20%20%20%23%20%D0%92%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D1%8C%20%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B5%20%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8%0A%20%20%20%20return%200%0A%0Adef%20constant%28n%3A%20int%29%3A%0A%20%20%20%20%22%22%22%D0%9F%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%BD%D0%B0%D1%8F%20%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C%22%22%22%0A%20%20%20%20%23%20%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D1%8B%2C%20%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5%20%D0%B8%20%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20%D0%B7%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%8E%D1%82%20O%281%29%20%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8%0A%20%20%20%20a%20%3D%200%0A%20%20%20%20nums%20%3D%20%5B0%5D%20%2A%2010%0A%20%20%20%20node%20%3D%20ListNode%280%29%0A%20%20%20%20%23%20%D0%9F%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5%20%D0%B2%20%D1%86%D0%B8%D0%BA%D0%BB%D0%B5%20%D0%B7%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%8E%D1%82%20O%281%29%20%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8%0A%20%20%20%20for%20_%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20c%20%3D%200%0A%20%20%20%20%23%20%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8%20%D0%B2%20%D1%86%D0%B8%D0%BA%D0%BB%D0%B5%20%D0%B7%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%8E%D1%82%20O%281%29%20%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8%0A%20%20%20%20for%20_%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20function%28%29%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%205%0A%20%20%20%20print%28%22%D0%A0%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%20%D0%B2%D1%85%D0%BE%D0%B4%D0%BD%D1%8B%D1%85%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20n%20%3D%22%2C%20n%29%0A%0A%20%20%20%20%23%20%D0%9F%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%BD%D0%B0%D1%8F%20%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C%0A%20%20%20%20constant%28n%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=6&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Во весь экран &gt;</a></div></p>
</details>
<h3 id="2-on">2. &nbsp; Линейная сложность <span class="arithmatex">\(O(n)\)</span><a class="headerlink" href="#2-on" title="Permanent link">&para;</a></h3>
<p>Линейная сложность часто встречается у массивов, связных списков, стеков, очередей и других структур, число элементов в которых пропорционально <span class="arithmatex">\(n\)</span> :</p>
<p>Линейная сложность часто встречается у массивов, списков, стеков, очередей и других структур, число элементов в которых пропорционально <span class="arithmatex">\(n\)</span> :</p>
<div class="tabbed-set tabbed-alternate" data-tabs="5:13"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><input id="__tabbed_5_11" name="__tabbed_5" type="radio" /><input id="__tabbed_5_12" name="__tabbed_5" type="radio" /><input id="__tabbed_5_13" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">Python</label><label for="__tabbed_5_2">C++</label><label for="__tabbed_5_3">Java</label><label for="__tabbed_5_4">C#</label><label for="__tabbed_5_5">Go</label><label for="__tabbed_5_6">Swift</label><label for="__tabbed_5_7">JS</label><label for="__tabbed_5_8">TS</label><label for="__tabbed_5_9">Dart</label><label for="__tabbed_5_10">Rust</label><label for="__tabbed_5_11">C</label><label for="__tabbed_5_12">Kotlin</label><label for="__tabbed_5_13">Ruby</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -6373,7 +6373,7 @@ O(1) &lt; O(\log n) &lt; O(n) &lt; O(n^2) &lt; O(2^n) \newline
<p align="center"> Рисунок 2-18 &nbsp; Квадратичная пространственная сложность, порождаемая рекурсивной функцией </p>
<h3 id="4-o2n">4. &nbsp; Экспоненциальная сложность <span class="arithmatex">\(O(2^n)\)</span><a class="headerlink" href="#4-o2n" title="Permanent link">&para;</a></h3>
<p>Экспоненциальная сложность часто встречается у бинарных деревьев. Обрати внимание на рисунок 2-19: "полное бинарное дерево" с <span class="arithmatex">\(n\)</span> уровнями содержит <span class="arithmatex">\(2^n - 1\)</span> узлов и занимает <span class="arithmatex">\(O(2^n)\)</span> пространства:</p>
<p>Экспоненциальная сложность часто встречается у бинарных деревьев. Полное бинарное дерево с <span class="arithmatex">\(n\)</span> уровнями содержит <span class="arithmatex">\(2^n - 1\)</span> узлов и занимает <span class="arithmatex">\(O(2^n)\)</span> пространства:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="9:13"><input checked="checked" id="__tabbed_9_1" name="__tabbed_9" type="radio" /><input id="__tabbed_9_2" name="__tabbed_9" type="radio" /><input id="__tabbed_9_3" name="__tabbed_9" type="radio" /><input id="__tabbed_9_4" name="__tabbed_9" type="radio" /><input id="__tabbed_9_5" name="__tabbed_9" type="radio" /><input id="__tabbed_9_6" name="__tabbed_9" type="radio" /><input id="__tabbed_9_7" name="__tabbed_9" type="radio" /><input id="__tabbed_9_8" name="__tabbed_9" type="radio" /><input id="__tabbed_9_9" name="__tabbed_9" type="radio" /><input id="__tabbed_9_10" name="__tabbed_9" type="radio" /><input id="__tabbed_9_11" name="__tabbed_9" type="radio" /><input id="__tabbed_9_12" name="__tabbed_9" type="radio" /><input id="__tabbed_9_13" name="__tabbed_9" type="radio" /><div class="tabbed-labels"><label for="__tabbed_9_1">Python</label><label for="__tabbed_9_2">C++</label><label for="__tabbed_9_3">Java</label><label for="__tabbed_9_4">C#</label><label for="__tabbed_9_5">Go</label><label for="__tabbed_9_6">Swift</label><label for="__tabbed_9_7">JS</label><label for="__tabbed_9_8">TS</label><label for="__tabbed_9_9">Dart</label><label for="__tabbed_9_10">Rust</label><label for="__tabbed_9_11">C</label><label for="__tabbed_9_12">Kotlin</label><label for="__tabbed_9_13">Ruby</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -6557,12 +6557,12 @@ O(1) &lt; O(\log n) &lt; O(n) &lt; O(n^2) &lt; O(2^n) \newline
<p align="center"> Рисунок 2-19 &nbsp; Экспоненциальная пространственная сложность, порождаемая полным бинарным деревом </p>
<h3 id="5-olog-n">5. &nbsp; Логарифмическая сложность <span class="arithmatex">\(O(\log n)\)</span><a class="headerlink" href="#5-olog-n" title="Permanent link">&para;</a></h3>
<p>Логарифмическая сложность часто встречается в алгоритмах "разделяй и властвуй". Например, при сортировке слиянием входной массив длины <span class="arithmatex">\(n\)</span> на каждом шаге рекурсии делится пополам по середине, образуя рекурсивное дерево высоты <span class="arithmatex">\(\log n\)</span> и используя <span class="arithmatex">\(O(\log n)\)</span> пространства кадров стека.</p>
<p>Логарифмическая сложность часто встречается в алгоритмах "разделяй и властвуй". Например, при сортировке слиянием входной массив длины <span class="arithmatex">\(n\)</span> на каждом шаге рекурсии делится пополам, образуя рекурсивное дерево высоты <span class="arithmatex">\(\log n\)</span> и используя <span class="arithmatex">\(O(\log n)\)</span> пространства кадров стека.</p>
<p>Еще один пример - преобразование числа в строку. Если задано положительное целое число <span class="arithmatex">\(n\)</span> , то количество его цифр равно <span class="arithmatex">\(\lfloor \log_{10} n \rfloor + 1\)</span> , то есть длина соответствующей строки тоже равна <span class="arithmatex">\(\lfloor \log_{10} n \rfloor + 1\)</span> , следовательно, пространственная сложность составляет <span class="arithmatex">\(O(\log_{10} n + 1) = O(\log n)\)</span> .</p>
<h2 id="244">2.4.4 &nbsp; Компромисс между временем и пространством<a class="headerlink" href="#244" title="Permanent link">&para;</a></h2>
<p>В идеале нам хотелось бы, чтобы и временная, и пространственная сложность алгоритма были оптимальными. Однако на практике одновременно оптимизировать и время, и память обычно очень трудно.</p>
<p><strong>Снижение временной сложности обычно достигается ценой увеличения пространственной сложности, и наоборот</strong>. Подход, при котором мы жертвуем памятью ради ускорения работы алгоритма, называется "обмен пространства на время"; обратный подход называется "обмен времени на пространство".</p>
<p>Выбор между этими двумя идеями зависит от того, что для нас важнее. В большинстве случаев время ценнее памяти, поэтому стратегия "обмена пространства на время" используется чаще. Но при очень больших объемах данных контроль пространственной сложности тоже становится крайне важным.</p>
<p>В идеальных условиях хотелось бы, чтобы и временная, и пространственная сложность алгоритма были оптимальными. Однако на практике одновременно оптимизировать и время, и память обычно очень трудно.</p>
<p><strong>Снижение временной сложности обычно достигается ценой увеличения пространственной сложности, и наоборот</strong>. Подход, при котором жертвуют памятью ради ускорения работы алгоритма, называется обменом пространства на время; обратный подход называется обменом времени на пространство.</p>
<p>Выбор между этими двумя идеями зависит от того, что важнее в конкретной задаче. В большинстве случаев время ценнее памяти, поэтому стратегия обмена пространства на время используется чаще. Но при очень больших объемах данных контроль пространственной сложности тоже становится крайне важным.</p>
<!-- Source file information -->