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 Что такое алгоритм
@@ -1253,7 +1253,7 @@
<span class="md-ellipsis">
Глава 4. Массив и связный список
Глава 4. Массивы и списки
@@ -1275,7 +1275,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 4. Массив и связный список
Глава 4. Массивы и списки
</label>
@@ -1381,7 +1381,7 @@
<span class="md-ellipsis">
4.4 Память и кеш *
4.4 Оперативная память и кэш *
@@ -1663,7 +1663,7 @@
<span class="md-ellipsis">
Глава 6. Хеширование
Глава 6. Хеш-таблицы
@@ -1685,7 +1685,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 6. Хеширование
Глава 6. Хеш-таблицы
</label>
@@ -1763,7 +1763,7 @@
<span class="md-ellipsis">
6.3 Хеш-алгоритмы
6.3 Алгоритмы хеширования
@@ -1858,7 +1858,7 @@
<span class="md-ellipsis">
Глава 7. Дерево
Глава 7. Деревья
@@ -1880,7 +1880,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 7. Дерево
Глава 7. Деревья
</label>
@@ -1958,7 +1958,7 @@
<span class="md-ellipsis">
7.3 Представление дерева массивом
7.3 Представление двоичного дерева массивом
@@ -2042,7 +2042,7 @@
<span class="md-ellipsis">
7.6 Резюме
7.6 Краткие итоги
@@ -2205,7 +2205,7 @@
<span class="md-ellipsis">
8.3 Задача Top-K
8.3 Задача Top-k
@@ -2296,7 +2296,7 @@
<span class="md-ellipsis">
Глава 9. Граф
Глава 9. Графы
@@ -2318,7 +2318,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 9. Граф
Глава 9. Графы
</label>
@@ -2368,7 +2368,7 @@
<span class="md-ellipsis">
9.2 Базовые операции над графами
9.2 Базовые операции графа
@@ -2424,7 +2424,7 @@
<span class="md-ellipsis">
9.4 Резюме
9.4 Краткие итоги
@@ -2563,7 +2563,7 @@
<span class="md-ellipsis">
10.2 Точка вставки двоичного поиска
10.2 Двоичный поиск точки вставки
@@ -2591,7 +2591,7 @@
<span class="md-ellipsis">
10.3 Граничные случаи двоичного поиска
10.3 Двоичный поиск границ
@@ -2619,7 +2619,7 @@
<span class="md-ellipsis">
10.4 Стратегия оптимизации через хеширование
10.4 Стратегии оптимизации хеширования
@@ -2647,7 +2647,7 @@
<span class="md-ellipsis">
10.5 Алгоритмы поиска: новый взгляд
10.5 Переосмысление алгоритмов поиска
@@ -2852,7 +2852,7 @@
<span class="md-ellipsis">
11.3 Пузырьковая сортировка
11.3 Сортировка пузырьком
@@ -2880,7 +2880,7 @@
<span class="md-ellipsis">
11.4 Сортировка вставкой
11.4 Сортировка вставками
@@ -3185,7 +3185,7 @@
<span class="md-ellipsis">
12.1 Алгоритмы разделяй и властвуй
12.1 Стратегия разделяй и властвуй
@@ -3213,7 +3213,7 @@
<span class="md-ellipsis">
12.2 Стратегия поиска разделяй и властвуй
12.2 Поисковая стратегия разделяй и властвуй
@@ -3490,7 +3490,7 @@
<span class="md-ellipsis">
13.4 Задача о $n$ ферзях
13.4 Задача о n ферзях
@@ -3631,7 +3631,7 @@
<span class="md-ellipsis">
14.1 Введение в динамическое программирование
14.1 Первое знакомство с динамическим программированием
@@ -3743,7 +3743,7 @@
<span class="md-ellipsis">
14.5 Задача о неограниченном рюкзаке
14.5 Задача о полном рюкзаке
@@ -4358,25 +4358,25 @@
<h3 id="1">1. &nbsp; Ключевые выводы<a class="headerlink" href="#1" title="Permanent link">&para;</a></h3>
<p><strong>Оценка эффективности алгоритмов</strong></p>
<ul>
<li>Временная эффективность и пространственная эффективность - два главных показателя, по которым оценивают качество алгоритма.</li>
<li>Мы можем оценивать эффективность алгоритма с помощью практического тестирования, но при этом трудно устранить влияние тестовой среды, а само тестирование потребляет много вычислительных ресурсов.</li>
<li>Анализ сложности устраняет недостатки практического тестирования, дает результаты, применимые ко всем платформам выполнения, и позволяет увидеть эффективность алгоритма при разных масштабах данных.</li>
<li>Временная и пространственная эффективность являются двумя основными критериями для оценки качества алгоритмов.</li>
<li>Эффективность алгоритмов можно оценивать с помощью практических тестов, однако это сложно из-за влияния тестовой среды и значительных затрат вычислительных ресурсов.</li>
<li>Анализ сложности позволяет устранить недостатки практических тестов, а результаты анализа применимы ко всем платформам и могут выявить эффективность алгоритма при различных объемах данных.</li>
</ul>
<p><strong>Временная сложность</strong></p>
<ul>
<li>Временная сложность используется для оценки того, как меняется время работы алгоритма с ростом объема данных. Она хорошо подходит для оценки эффективности, но в некоторых случаях может давать недостаточно точное сравнение, например когда входные данные малы или когда временные сложности совпадают.</li>
<li>Худшая временная сложность обозначается с помощью нотации Big <span class="arithmatex">\(O\)</span> и соответствует асимптотической верхней границе функции, отражая уровень роста числа операций <span class="arithmatex">\(T(n)\)</span> при стремлении <span class="arithmatex">\(n\)</span> к положительной бесконечности.</li>
<li>Вывод временной сложности включает два шага: сначала подсчитывается число операций, затем определяется асимптотическая верхняя граница.</li>
<li>Распространенные временные сложности в порядке роста: <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n \log n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span>, <span class="arithmatex">\(O(2^n)\)</span> и <span class="arithmatex">\(O(n!)\)</span>.</li>
<li>Временная сложность некоторых алгоритмов не фиксирована, а зависит от распределения входных данных. Различают худшую, лучшую и среднюю временную сложность; лучшая временная сложность используется редко, потому что для ее достижения вход обычно должен удовлетворять строгим условиям.</li>
<li>Средняя временная сложность отражает эффективность алгоритма на случайных входных данных и ближе всего к его поведению в практических сценариях. Для ее вычисления нужно знать распределение входных данных и рассчитать соответствующее математическое ожидание.</li>
<li>Временная сложность используется для оценки тенденции изменения времени выполнения алгоритма с увеличением объема данных, что позволяет оценивать его эффективность. Однако в некоторых случаях она может работать не так хорошо, например когда объем входных данных мал или временная сложность одинакова, что не позволяет точно сравнить эффективность алгоритмов.</li>
<li>Худшая временная сложность обозначается символом Big <span class="arithmatex">\(O\)</span> и соответствует асимптотической верхней границе, отражая уровень роста количества операций <span class="arithmatex">\(T(n)\)</span> при стремлении <span class="arithmatex">\(n\)</span> к бесконечности.</li>
<li>Определение временной сложности включает два этапа: сначала подсчитывается количество операций, затем определяется асимптотическая верхняя граница.</li>
<li>Наиболее распространенные временные сложности в порядке возрастания: <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n \log n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span>, <span class="arithmatex">\(O(2^n)\)</span> и <span class="arithmatex">\(O(n!)\)</span>.</li>
<li>Временная сложность некоторых алгоритмов не является фиксированной и зависит от распределения входных данных. Временная сложность делится на худшую, лучшую и среднюю. Лучшая временная сложность почти не используется, так как для достижения лучшего случая входные данные должны соответствовать строгим критериям.</li>
<li>Средняя временная сложность отражает эффективность алгоритма при случайных входных данных и наиболее близка к реальной производительности алгоритма. Для расчета средней временной сложности необходимо учитывать распределение входных данных и математическое ожидание.</li>
</ul>
<p><strong>Пространственная сложность</strong></p>
<ul>
<li>Пространственная сложность играет роль, аналогичную временной: она показывает тенденцию роста потребления памяти по мере увеличения объема данных.</li>
<li>Память, связанная с выполнением алгоритма, можно разделить на входное пространство, временное пространство и выходное пространство. Обычно входное пространство не включается в расчет пространственной сложности. Временное пространство можно разбить на временные данные, пространство кадров стека и пространство инструкций; при этом пространство кадров стека обычно влияет на сложность только в рекурсивных функциях.</li>
<li>Обычно нас интересует только худшая пространственная сложность, то есть пространственная сложность алгоритма при худшем наборе входных данных и в худший момент времени выполнения.</li>
<li>Распространенные пространственные сложности в порядке роста: <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span> и <span class="arithmatex">\(O(2^n)\)</span>.</li>
<li>Пространственная сложность аналогична временной сложности и используется для оценки тенденции изменения объема памяти, занимаемой алгоритмом, с увеличением объема данных.</li>
<li>Память, используемую в процессе выполнения алгоритма, можно разделить на входное пространство, временное пространство и выходное пространство. Обычно при расчете пространственной сложности входное пространство не учитывается. Временное пространство делится на временные данные, пространство стека и пространство инструкций, причем пространство стека обычно влияет на сложность только в рекурсивных функциях.</li>
<li>Обычно рассматривается только худшая пространственная сложность, то есть пространственная сложность алгоритма при худших входных данных и в худший момент выполнения.</li>
<li>Наиболее распространенные пространственные сложности в порядке возрастания: <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span> и <span class="arithmatex">\(O(2^n)\)</span>.</li>
</ul>
<h3 id="2-q-a">2. &nbsp; Q &amp; A<a class="headerlink" href="#2-q-a" title="Permanent link">&para;</a></h3>
<p><strong>Q</strong>: Является ли пространственная сложность хвостовой рекурсии равной <span class="arithmatex">\(O(1)\)</span>?</p>