mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-11 23:16:07 +00:00
deploy
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -4205,7 +4205,7 @@
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
16.3 Terminology Table
|
||||
16.3 Glossary
|
||||
|
||||
|
||||
|
||||
@@ -4411,7 +4411,7 @@
|
||||
<p><img alt="Number of ways to reach the 3rd step" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_example.png" /></p>
|
||||
<p align="center"> Figure 14-1 Number of ways to reach the 3rd step </p>
|
||||
|
||||
<p>The goal of this problem is to find the number of ways, <strong>we can consider using backtracking to enumerate all possibilities</strong>. Specifically, imagine climbing stairs as a multi-round selection process: starting from the ground, choosing to go up <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps in each round, incrementing the count by <span class="arithmatex">\(1\)</span> whenever the top of the stairs is reached, and pruning when exceeding the top. The code is as follows:</p>
|
||||
<p>The goal of this problem is to determine the number of ways, so <strong>we can consider using backtracking to enumerate all possibilities</strong>. Specifically, imagine climbing stairs as a multi-round selection process: starting from the ground, choosing to go up <span class="arithmatex">\(1\)</span> or <span class="arithmatex">\(2\)</span> steps in each round, incrementing the count by <span class="arithmatex">\(1\)</span> whenever the top of the stairs is reached, and pruning when exceeding the top. The code is as follows:</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">
|
||||
@@ -4801,12 +4801,12 @@ dp[i-1], dp[i-2], \dots, dp[2], dp[1]
|
||||
<div class="arithmatex">\[
|
||||
dp[i] = dp[i-1] + dp[i-2]
|
||||
\]</div>
|
||||
<p>This means that in the stair climbing problem, there exists a recurrence relation among the subproblems, <strong>the solution to the original problem can be constructed from the solutions to the subproblems</strong>. Figure 14-2 illustrates this recurrence relation.</p>
|
||||
<p>This means that in the stair climbing problem, there exists a recurrence relation among the subproblems, and <strong>the solution to the original problem can be constructed from the solutions to the subproblems</strong>. Figure 14-2 illustrates this recurrence relation.</p>
|
||||
<p><img alt="Recurrence relation for the number of ways" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png" /></p>
|
||||
<p align="center"> Figure 14-2 Recurrence relation for the number of ways </p>
|
||||
|
||||
<p>We can obtain a brute force search solution based on the recurrence formula. Starting from <span class="arithmatex">\(dp[n]\)</span>, <strong>recursively decompose a larger problem into the sum of two smaller problems</strong>, until reaching the smallest subproblems <span class="arithmatex">\(dp[1]\)</span> and <span class="arithmatex">\(dp[2]\)</span> and returning. Among them, the solutions to the smallest subproblems are known, namely <span class="arithmatex">\(dp[1] = 1\)</span> and <span class="arithmatex">\(dp[2] = 2\)</span>, representing <span class="arithmatex">\(1\)</span> and <span class="arithmatex">\(2\)</span> ways to climb to the <span class="arithmatex">\(1\)</span>st and <span class="arithmatex">\(2\)</span>nd steps, respectively.</p>
|
||||
<p>Observe the following code, which, like standard backtracking code, belongs to depth-first search but is more concise:</p>
|
||||
<p>Observe the following code: like standard backtracking code, it also uses depth-first search but is more concise:</p>
|
||||
<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">
|
||||
<div class="tabbed-block">
|
||||
@@ -5027,7 +5027,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Figure 14-3 shows the recursion tree formed by brute force search. For the problem <span class="arithmatex">\(dp[n]\)</span>, the depth of its recursion tree is <span class="arithmatex">\(n\)</span>, with a time complexity of <span class="arithmatex">\(O(2^n)\)</span>. Exponential order represents explosive growth; if we input a relatively large <span class="arithmatex">\(n\)</span>, we will fall into a long wait.</p>
|
||||
<p>Figure 14-3 shows the recursion tree formed by brute force search. For the problem <span class="arithmatex">\(dp[n]\)</span>, the depth of its recursion tree is <span class="arithmatex">\(n\)</span>, with a time complexity of <span class="arithmatex">\(O(2^n)\)</span>. Exponential growth is explosive; if we input a relatively large <span class="arithmatex">\(n\)</span>, the wait can be very long.</p>
|
||||
<p><img alt="Recursion tree for climbing stairs" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png" /></p>
|
||||
<p align="center"> Figure 14-3 Recursion tree for climbing stairs </p>
|
||||
|
||||
@@ -5361,7 +5361,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Observe Figure 14-4, <strong>after memoization, all overlapping subproblems only need to be computed once, optimizing the time complexity to <span class="arithmatex">\(O(n)\)</span></strong>, which is a tremendous leap.</p>
|
||||
<p>Observe Figure 14-4: <strong>after memoization, all overlapping subproblems need to be computed only once, reducing the time complexity to <span class="arithmatex">\(O(n)\)</span></strong>, which is a tremendous leap.</p>
|
||||
<p><img alt="Recursion tree with memoization" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png" /></p>
|
||||
<p align="center"> Figure 14-4 Recursion tree with memoization </p>
|
||||
|
||||
@@ -5616,7 +5616,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
<li>The recurrence formula <span class="arithmatex">\(dp[i] = dp[i-1] + dp[i-2]\)</span> is called the <u>state transition equation</u>.</li>
|
||||
</ul>
|
||||
<h2 id="1414-space-optimization">14.1.4 Space Optimization<a class="headerlink" href="#1414-space-optimization" title="Permanent link">¶</a></h2>
|
||||
<p>Observant readers may have noticed that <strong>since <span class="arithmatex">\(dp[i]\)</span> is only related to <span class="arithmatex">\(dp[i-1]\)</span> and <span class="arithmatex">\(dp[i-2]\)</span>, we do not need to use an array <code>dp</code> to store the solutions to all subproblems</strong>, but can simply use two variables to roll forward. The code is as follows:</p>
|
||||
<p>Observant readers may have noticed that <strong>since <span class="arithmatex">\(dp[i]\)</span> is only related to <span class="arithmatex">\(dp[i-1]\)</span> and <span class="arithmatex">\(dp[i-2]\)</span>, we do not need to use an array <code>dp</code> to store the solutions to all subproblems</strong>, and can instead use two variables that roll forward. The code is as follows:</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">
|
||||
@@ -5809,7 +5809,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Observing the above code, since the space occupied by the array <code>dp</code> is saved, the space complexity is reduced from <span class="arithmatex">\(O(n)\)</span> to <span class="arithmatex">\(O(1)\)</span>.</p>
|
||||
<p>As the above code shows, by eliminating the space occupied by the array <code>dp</code>, the space complexity is reduced from <span class="arithmatex">\(O(n)\)</span> to <span class="arithmatex">\(O(1)\)</span>.</p>
|
||||
<p>In dynamic programming problems, the current state often depends only on a limited number of preceding states, allowing us to retain only the necessary states and save memory space through "dimension reduction". <strong>This space optimization technique is called "rolling variable" or "rolling array"</strong>.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
Reference in New Issue
Block a user