mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-10 22:46:07 +00:00
deploy
This commit is contained in:
@@ -4535,7 +4535,7 @@
|
||||
<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>
|
||||
@@ -4864,7 +4864,7 @@
|
||||
<p>Рассмотрим следующий код. Понятие худшей пространственной сложности здесь имеет два значения.</p>
|
||||
<ol>
|
||||
<li><strong>Ориентир на худшие входные данные</strong>: когда <span class="arithmatex">\(n < 10\)</span> , пространственная сложность равна <span class="arithmatex">\(O(1)\)</span> ; но когда <span class="arithmatex">\(n > 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">
|
||||
@@ -5246,7 +5246,7 @@
|
||||
</div>
|
||||
<p>Функции <code>loop()</code> и <code>recur()</code> имеют временную сложность <span class="arithmatex">\(O(n)\)</span> , но их пространственная сложность различается.</p>
|
||||
<ul>
|
||||
<li>Функция <code>loop()</code> вызывает <code>function()</code> в цикле <span class="arithmatex">\(n\)</span> раз; на каждой итерации <code>function()</code> возвращается и освобождает пространство своего кадра стека, поэтому пространственная сложность по-прежнему равна <span class="arithmatex">\(O(1)\)</span> .</li>
|
||||
<li>Функция <code>loop()</code> вызывает <code>function()</code> в цикле <span class="arithmatex">\(n\)</span> раз. На каждой итерации <code>function()</code> возвращается и освобождает пространство своего кадра стека, поэтому пространственная сложность по-прежнему равна <span class="arithmatex">\(O(1)\)</span> .</li>
|
||||
<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 Распространенные типы<a class="headerlink" href="#243" title="Permanent link">¶</a></h2>
|
||||
@@ -6207,7 +6207,7 @@
|
||||
<p><div style="height: 405px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20quadratic%28n%3A%20int%29%3A%0A%20%20%20%20%22%22%22%D0%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%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%94%D0%B2%D1%83%D0%BC%D0%B5%D1%80%D0%BD%D1%8B%D0%B9%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%B7%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D0%B5%D1%82%20O%28n%5E2%29%20%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8%0A%20%20%20%20num_matrix%20%3D%20%5B%5B0%5D%20%2A%20n%20for%20_%20in%20range%28n%29%5D%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%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%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%20quadratic%28n%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=16&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
|
||||
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=def%20quadratic%28n%3A%20int%29%3A%0A%20%20%20%20%22%22%22%D0%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%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%94%D0%B2%D1%83%D0%BC%D0%B5%D1%80%D0%BD%D1%8B%D0%B9%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%B7%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D0%B5%D1%82%20O%28n%5E2%29%20%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8%0A%20%20%20%20num_matrix%20%3D%20%5B%5B0%5D%20%2A%20n%20for%20_%20in%20range%28n%29%5D%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%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%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%20quadratic%28n%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=16&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Во весь экран ></a></div></p>
|
||||
</details>
|
||||
<p>Как показано на рисунке 2-18, глубина рекурсии этой функции равна <span class="arithmatex">\(n\)</span> , и в каждой рекурсивной функции инициализируется массив длины <span class="arithmatex">\(n\)</span> , <span class="arithmatex">\(n-1\)</span> , <span class="arithmatex">\(\dots\)</span> , <span class="arithmatex">\(2\)</span> , <span class="arithmatex">\(1\)</span> ; его средняя длина равна <span class="arithmatex">\(n / 2\)</span> , поэтому в сумме используется <span class="arithmatex">\(O(n^2)\)</span> пространства:</p>
|
||||
<p>Как показано на рисунке 2-18, глубина рекурсии этой функции равна <span class="arithmatex">\(n\)</span> , и в каждой рекурсивной функции инициализируется массив длины <span class="arithmatex">\(n\)</span> , <span class="arithmatex">\(n-1\)</span> , <span class="arithmatex">\(\dots\)</span> , <span class="arithmatex">\(2\)</span> , <span class="arithmatex">\(1\)</span>. Его средняя длина равна <span class="arithmatex">\(n / 2\)</span> , поэтому в сумме используется <span class="arithmatex">\(O(n^2)\)</span> пространства:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="8:13"><input checked="checked" id="__tabbed_8_1" name="__tabbed_8" type="radio" /><input id="__tabbed_8_2" name="__tabbed_8" type="radio" /><input id="__tabbed_8_3" name="__tabbed_8" type="radio" /><input id="__tabbed_8_4" name="__tabbed_8" type="radio" /><input id="__tabbed_8_5" name="__tabbed_8" type="radio" /><input id="__tabbed_8_6" name="__tabbed_8" type="radio" /><input id="__tabbed_8_7" name="__tabbed_8" type="radio" /><input id="__tabbed_8_8" name="__tabbed_8" type="radio" /><input id="__tabbed_8_9" name="__tabbed_8" type="radio" /><input id="__tabbed_8_10" name="__tabbed_8" type="radio" /><input id="__tabbed_8_11" name="__tabbed_8" type="radio" /><input id="__tabbed_8_12" name="__tabbed_8" type="radio" /><input id="__tabbed_8_13" name="__tabbed_8" type="radio" /><div class="tabbed-labels"><label for="__tabbed_8_1">Python</label><label for="__tabbed_8_2">C++</label><label for="__tabbed_8_3">Java</label><label for="__tabbed_8_4">C#</label><label for="__tabbed_8_5">Go</label><label for="__tabbed_8_6">Swift</label><label for="__tabbed_8_7">JS</label><label for="__tabbed_8_8">TS</label><label for="__tabbed_8_9">Dart</label><label for="__tabbed_8_10">Rust</label><label for="__tabbed_8_11">C</label><label for="__tabbed_8_12">Kotlin</label><label for="__tabbed_8_13">Ruby</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -6375,7 +6375,7 @@
|
||||
<p align="center"> Рисунок 2-18 Квадратичная пространственная сложность, порождаемая рекурсивной функцией </p>
|
||||
|
||||
<h3 id="4-o2n">4. Экспоненциальная сложность <span class="arithmatex">\(O(2^n)\)</span><a class="headerlink" href="#4-o2n" title="Permanent link">¶</a></h3>
|
||||
<p>Экспоненциальная сложность часто встречается у бинарных деревьев. Полное бинарное дерево с <span class="arithmatex">\(n\)</span> уровнями содержит <span class="arithmatex">\(2^n - 1\)</span> узлов и занимает <span class="arithmatex">\(O(2^n)\)</span> пространства:</p>
|
||||
<p>Экспоненциальная сложность часто встречается у бинарных деревьев. Как видно на рисунке 2-19, полное бинарное дерево с <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">
|
||||
@@ -6559,11 +6559,11 @@
|
||||
<p align="center"> Рисунок 2-19 Экспоненциальная пространственная сложность, порождаемая полным бинарным деревом </p>
|
||||
|
||||
<h3 id="5-olog-n">5. Логарифмическая сложность <span class="arithmatex">\(O(\log n)\)</span><a class="headerlink" href="#5-olog-n" title="Permanent link">¶</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 Компромисс между временем и пространством<a class="headerlink" href="#244" title="Permanent link">¶</a></h2>
|
||||
<p>В идеальных условиях хотелось бы, чтобы и временная, и пространственная сложность алгоритма были оптимальными. Однако на практике одновременно оптимизировать и время, и память обычно очень трудно.</p>
|
||||
<p><strong>Снижение временной сложности обычно достигается ценой увеличения пространственной сложности, и наоборот</strong>. Подход, при котором жертвуют памятью ради ускорения работы алгоритма, называется обменом пространства на время; обратный подход называется обменом времени на пространство.</p>
|
||||
<p><strong>Снижение временной сложности обычно достигается ценой увеличения пространственной сложности, и наоборот</strong>. Подход, при котором жертвуют памятью ради ускорения работы алгоритма, называется обменом пространства на время. Обратный подход называется обменом времени на пространство.</p>
|
||||
<p>Выбор между этими двумя идеями зависит от того, что важнее в конкретной задаче. В большинстве случаев время ценнее памяти, поэтому стратегия обмена пространства на время используется чаще. Но при очень больших объемах данных контроль пространственной сложности тоже становится крайне важным.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
Reference in New Issue
Block a user