This commit is contained in:
krahets
2026-04-02 03:08:50 +08:00
parent 09a136c9fa
commit aaf9f58eb3
157 changed files with 3002 additions and 2994 deletions

View File

@@ -6,7 +6,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Data Structures and Algorithms Crash Course with Animated Illustrations and Off-the-Shelf Code">
<meta name="description" content="Data structures and algorithms tutorial with animated illustrations and ready-to-run code">
<meta name="author" content="krahets">
@@ -576,7 +576,7 @@
<span class="md-ellipsis">
Chapter 1. Encounter With Algorithms
Chapter 1. Encounter with Algorithms
@@ -598,7 +598,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 1. Encounter With Algorithms
Chapter 1. Encounter with Algorithms
</label>
@@ -1183,7 +1183,7 @@
<span class="md-ellipsis">
Chapter 4. Array and Linked List
Chapter 4. Arrays and Linked Lists
@@ -1205,7 +1205,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 4. Array and Linked List
Chapter 4. Arrays and Linked Lists
</label>
@@ -1311,7 +1311,7 @@
<span class="md-ellipsis">
4.4 Memory and Cache *
4.4 Random-Access Memory and Cache *
@@ -1402,7 +1402,7 @@
<span class="md-ellipsis">
Chapter 5. Stack and Queue
Chapter 5. Stacks and Queues
@@ -1424,7 +1424,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 5. Stack and Queue
Chapter 5. Stacks and Queues
</label>
@@ -1502,7 +1502,7 @@
<span class="md-ellipsis">
5.3 Double-Ended Queue
5.3 Deque
@@ -1593,7 +1593,7 @@
<span class="md-ellipsis">
Chapter 6. Hashing
Chapter 6. Hash Table
@@ -1615,7 +1615,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 6. Hashing
Chapter 6. Hash Table
</label>
@@ -1888,7 +1888,7 @@
<span class="md-ellipsis">
7.3 Array Representation of Tree
7.3 Array Representation of Binary Trees
@@ -2107,7 +2107,7 @@
<span class="md-ellipsis">
8.2 Building a Heap
8.2 Heap Construction Operation
@@ -2135,7 +2135,7 @@
<span class="md-ellipsis">
8.3 Top-K Problem
8.3 Top-k Problem
@@ -2493,7 +2493,7 @@
<span class="md-ellipsis">
10.2 Binary Search Insertion
10.2 Binary Search Insertion Point
@@ -2521,7 +2521,7 @@
<span class="md-ellipsis">
10.3 Binary Search Edge Cases
10.3 Binary Search Boundaries
@@ -2577,7 +2577,7 @@
<span class="md-ellipsis">
10.5 Search Algorithms Revisited
10.5 Searching Algorithms Revisited
@@ -2726,7 +2726,7 @@
<span class="md-ellipsis">
11.1 Sorting Algorithms
11.1 Sorting Algorithm
@@ -3199,7 +3199,7 @@
<span class="md-ellipsis">
12.4 Hanoi Tower Problem
12.4 Hanota Problem
@@ -4183,7 +4183,7 @@
<span class="md-ellipsis">
16.3 Terminology Table
16.3 Glossary
@@ -4368,7 +4368,7 @@
<p>We make a slight modification to the stair climbing problem to make it more suitable for demonstrating the concept of optimal substructure.</p>
<div class="admonition question">
<p class="admonition-title">Climbing stairs with minimum cost</p>
<p>Given a staircase, where you can climb <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps at a time, and each step has a non-negative integer representing the cost you need to pay at that step. Given a non-negative integer array <span class="arithmatex">\(cost\)</span>, where <span class="arithmatex">\(cost[i]\)</span> represents the cost at the <span class="arithmatex">\(i\)</span>-th step, and <span class="arithmatex">\(cost[0]\)</span> is the ground (starting point). What is the minimum cost required to reach the top?</p>
<p>Given a staircase, you can climb <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps at a time, and each step is labeled with a non-negative integer representing the cost of stepping on it. Given a non-negative integer array <span class="arithmatex">\(cost\)</span>, where <span class="arithmatex">\(cost[i]\)</span> represents the cost of the <span class="arithmatex">\(i\)</span>-th step and <span class="arithmatex">\(cost[0]\)</span> is the ground (starting point), what is the minimum cost required to reach the top?</p>
</div>
<p>As shown in Figure 14-6, if the costs of the <span class="arithmatex">\(1\)</span>st, <span class="arithmatex">\(2\)</span>nd, and <span class="arithmatex">\(3\)</span>rd steps are <span class="arithmatex">\(1\)</span>, <span class="arithmatex">\(10\)</span>, and <span class="arithmatex">\(1\)</span> respectively, then climbing from the ground to the <span class="arithmatex">\(3\)</span>rd step requires a minimum cost of <span class="arithmatex">\(2\)</span>.</p>
<p><img alt="Minimum cost to climb to the 3rd step" class="animation-figure" src="../dp_problem_features.assets/min_cost_cs_example.png" /></p>
@@ -4879,7 +4879,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
<p class="admonition-title">Climbing stairs with constraint</p>
<p>Given a staircase with <span class="arithmatex">\(n\)</span> steps, where you can climb <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps at a time, <strong>but you cannot jump <span class="arithmatex">\(1\)</span> step in two consecutive rounds</strong>. How many ways are there to climb to the top?</p>
</div>
<p>As shown in Figure 14-8, there are only <span class="arithmatex">\(2\)</span> feasible ways to climb to the <span class="arithmatex">\(3\)</span>rd step. The way of jumping <span class="arithmatex">\(1\)</span> step three consecutive times does not satisfy the constraint and is therefore discarded.</p>
<p>As shown in Figure 14-8, there are only <span class="arithmatex">\(2\)</span> feasible ways to climb to the <span class="arithmatex">\(3\)</span>rd step. The path with three consecutive <span class="arithmatex">\(1\)</span>-step jumps does not satisfy the constraint and is therefore discarded.</p>
<p><img alt="Number of ways to climb to the 3rd step with constraint" class="animation-figure" src="../dp_problem_features.assets/climbing_stairs_constraint_example.png" /></p>
<p align="center"> Figure 14-8 &nbsp; Number of ways to climb to the 3rd step with constraint </p>
@@ -4887,8 +4887,8 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
<p>It is not difficult to see that this problem no longer satisfies no aftereffects, and the state transition equation <span class="arithmatex">\(dp[i] = dp[i-1] + dp[i-2]\)</span> also fails, because <span class="arithmatex">\(dp[i-1]\)</span> represents jumping <span class="arithmatex">\(1\)</span> step in this round, but it includes many solutions where "the previous round was a jump of <span class="arithmatex">\(1\)</span> step", which cannot be directly counted in <span class="arithmatex">\(dp[i]\)</span> to satisfy the constraint.</p>
<p>For this reason, we need to expand the state definition: <strong>state <span class="arithmatex">\([i, j]\)</span> represents being on the <span class="arithmatex">\(i\)</span>-th step with the previous round having jumped <span class="arithmatex">\(j\)</span> steps</strong>, where <span class="arithmatex">\(j \in \{1, 2\}\)</span>. This state definition effectively distinguishes whether the previous round was a jump of <span class="arithmatex">\(1\)</span> step or <span class="arithmatex">\(2\)</span> steps, allowing us to determine where the current state came from.</p>
<ul>
<li>When the previous round jumped <span class="arithmatex">\(1\)</span> step, the round before that could only choose to jump <span class="arithmatex">\(2\)</span> steps, i.e., <span class="arithmatex">\(dp[i, 1]\)</span> can only be transferred from <span class="arithmatex">\(dp[i-1, 2]\)</span>.</li>
<li>When the previous round jumped <span class="arithmatex">\(2\)</span> steps, the round before that could choose to jump <span class="arithmatex">\(1\)</span> step or <span class="arithmatex">\(2\)</span> steps, i.e., <span class="arithmatex">\(dp[i, 2]\)</span> can be transferred from <span class="arithmatex">\(dp[i-2, 1]\)</span> or <span class="arithmatex">\(dp[i-2, 2]\)</span>.</li>
<li>When the previous round jumped <span class="arithmatex">\(1\)</span> step, the round before that could only choose to jump <span class="arithmatex">\(2\)</span> steps, i.e., <span class="arithmatex">\(dp[i, 1]\)</span> can only transition from <span class="arithmatex">\(dp[i-1, 2]\)</span>.</li>
<li>When the previous round jumped <span class="arithmatex">\(2\)</span> steps, the round before that could choose to jump <span class="arithmatex">\(1\)</span> step or <span class="arithmatex">\(2\)</span> steps, i.e., <span class="arithmatex">\(dp[i, 2]\)</span> can transition from <span class="arithmatex">\(dp[i-2, 1]\)</span> or <span class="arithmatex">\(dp[i-2, 2]\)</span>.</li>
</ul>
<p>As shown in Figure 14-9, under this definition, <span class="arithmatex">\(dp[i, j]\)</span> represents the number of ways for state <span class="arithmatex">\([i, j]\)</span>. The state transition equation is then:</p>
<div class="arithmatex">\[
@@ -5196,10 +5196,10 @@ dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
<p>In the above case, since we only need to consider one more preceding state, we can still make the problem satisfy no aftereffects by expanding the state definition. However, some problems have very severe "aftereffects".</p>
<div class="admonition question">
<p class="admonition-title">Climbing stairs with obstacle generation</p>
<p>Given a staircase with <span class="arithmatex">\(n\)</span> steps, where you can climb <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps at a time. <strong>It is stipulated that when climbing to the <span class="arithmatex">\(i\)</span>-th step, the system will automatically place an obstacle on the <span class="arithmatex">\(2i\)</span>-th step, and thereafter no round is allowed to jump to the <span class="arithmatex">\(2i\)</span>-th step</strong>. For example, if the first two rounds jump to the <span class="arithmatex">\(2\)</span>nd and <span class="arithmatex">\(3\)</span>rd steps, then afterwards you cannot jump to the <span class="arithmatex">\(4\)</span>th and <span class="arithmatex">\(6\)</span>th steps. How many ways are there to climb to the top?</p>
<p>Given a staircase with <span class="arithmatex">\(n\)</span> steps, where you can climb <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps at a time. <strong>Whenever you reach the <span class="arithmatex">\(i\)</span>-th step, the system automatically places an obstacle on the <span class="arithmatex">\(2i\)</span>-th step, and no subsequent round is allowed to jump to the <span class="arithmatex">\(2i\)</span>-th step</strong>. For example, if the first two rounds jump to the <span class="arithmatex">\(2\)</span>nd and <span class="arithmatex">\(3\)</span>rd steps, then afterwards you cannot jump to the <span class="arithmatex">\(4\)</span>th and <span class="arithmatex">\(6\)</span>th steps. How many ways are there to climb to the top?</p>
</div>
<p>In this problem, the next jump depends on all past states, because each jump places obstacles on higher steps, affecting future jumps. For such problems, dynamic programming is often difficult to solve.</p>
<p>In fact, many complex combinatorial optimization problems (such as the traveling salesman problem) do not satisfy no aftereffects. For such problems, we usually choose to use other methods, such as heuristic search, genetic algorithms, reinforcement learning, etc., to obtain usable local optimal solutions within a limited time.</p>
<p>In fact, many complex combinatorial optimization problems (such as the traveling salesman problem) do not satisfy no aftereffects. For such problems, we usually use other methods, such as heuristic search, genetic algorithms, and reinforcement learning, to obtain usable locally optimal solutions within a limited time.</p>
<!-- Source file information -->