mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-24 09:07:14 +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
|
||||
|
||||
|
||||
|
||||
@@ -2504,7 +2504,7 @@
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
10.2 Binary Search Insertion
|
||||
10.2 Binary Search Insertion Point
|
||||
|
||||
|
||||
|
||||
@@ -2522,7 +2522,7 @@
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
10.2 Binary Search Insertion
|
||||
10.2 Binary Search Insertion Point
|
||||
|
||||
|
||||
|
||||
@@ -2593,7 +2593,7 @@
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
10.3 Binary Search Edge Cases
|
||||
10.3 Binary Search Boundaries
|
||||
|
||||
|
||||
|
||||
@@ -2649,7 +2649,7 @@
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
10.5 Search Algorithms Revisited
|
||||
10.5 Searching Algorithms Revisited
|
||||
|
||||
|
||||
|
||||
@@ -2798,7 +2798,7 @@
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
11.1 Sorting Algorithms
|
||||
11.1 Sorting Algorithm
|
||||
|
||||
|
||||
|
||||
@@ -3271,7 +3271,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
|
||||
|
||||
|
||||
|
||||
@@ -4357,11 +4357,11 @@
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="102-binary-search-insertion-point">10.2 Binary Search Insertion Point<a class="headerlink" href="#102-binary-search-insertion-point" title="Permanent link">¶</a></h1>
|
||||
<p>Binary search can not only be used to search for target elements but also to solve many variant problems, such as searching for the insertion position of a target element.</p>
|
||||
<p>Binary search can be used not only to search for target elements, but also to solve many variant problems, such as finding the insertion position of a target element.</p>
|
||||
<h2 id="1021-case-without-duplicate-elements">10.2.1 Case Without Duplicate Elements<a class="headerlink" href="#1021-case-without-duplicate-elements" title="Permanent link">¶</a></h2>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>Given a sorted array <code>nums</code> of length <span class="arithmatex">\(n\)</span> and an element <code>target</code>, where the array contains no duplicate elements. Insert <code>target</code> into the array <code>nums</code> while maintaining its sorted order. If the array already contains the element <code>target</code>, insert it to its left. Return the index of <code>target</code> in the array after insertion. An example is shown in Figure 10-4.</p>
|
||||
<p>Given a sorted array <code>nums</code> of length <span class="arithmatex">\(n\)</span> and an element <code>target</code>, where the array contains no duplicate elements, insert <code>target</code> into <code>nums</code> while maintaining its sorted order. If <code>target</code> already exists in the array, insert it to its left. Return the index of <code>target</code> after insertion. An example is shown below.</p>
|
||||
</div>
|
||||
<p><img alt="Binary search insertion point example data" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_example.png" /></p>
|
||||
<p align="center"> Figure 10-4 Binary search insertion point example data </p>
|
||||
@@ -4370,8 +4370,8 @@
|
||||
<p><strong>Question 1</strong>: When the array contains <code>target</code>, is the insertion point index the same as that element's index?</p>
|
||||
<p>The problem requires inserting <code>target</code> to the left of equal elements, which means the newly inserted <code>target</code> replaces the position of the original <code>target</code>. In other words, <strong>when the array contains <code>target</code>, the insertion point index is the index of that <code>target</code></strong>.</p>
|
||||
<p><strong>Question 2</strong>: When the array does not contain <code>target</code>, what is the insertion point index?</p>
|
||||
<p>Further consider the binary search process: When <code>nums[m] < target</code>, <span class="arithmatex">\(i\)</span> moves, which means pointer <span class="arithmatex">\(i\)</span> is approaching elements greater than or equal to <code>target</code>. Similarly, pointer <span class="arithmatex">\(j\)</span> is always approaching elements less than or equal to <code>target</code>.</p>
|
||||
<p>Therefore, when the binary search ends, we must have: <span class="arithmatex">\(i\)</span> points to the first element greater than <code>target</code>, and <span class="arithmatex">\(j\)</span> points to the first element less than <code>target</code>. <strong>It's easy to see that when the array does not contain <code>target</code>, the insertion index is <span class="arithmatex">\(i\)</span></strong>. The code is shown below:</p>
|
||||
<p>To analyze this further, consider the binary search process: when <code>nums[m] < target</code>, <span class="arithmatex">\(i\)</span> moves, meaning that pointer <span class="arithmatex">\(i\)</span> is approaching elements greater than or equal to <code>target</code>. Similarly, pointer <span class="arithmatex">\(j\)</span> is always approaching elements less than or equal to <code>target</code>.</p>
|
||||
<p>Therefore, when the binary search ends, <span class="arithmatex">\(i\)</span> must point to the first element greater than <code>target</code>, and <span class="arithmatex">\(j\)</span> must point to the first element less than <code>target</code>. <strong>It follows that when the array does not contain <code>target</code>, the insertion index is <span class="arithmatex">\(i\)</span></strong>. The code is shown below:</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">
|
||||
@@ -4643,7 +4643,7 @@
|
||||
<p>Based on the previous problem, assume the array may contain duplicate elements, with everything else remaining the same.</p>
|
||||
</div>
|
||||
<p>Suppose there are multiple <code>target</code> elements in the array. Ordinary binary search can only return the index of one <code>target</code>, <strong>and cannot determine how many <code>target</code> elements are to the left and right of that element</strong>.</p>
|
||||
<p>The problem requires inserting the target element at the leftmost position, <strong>so we need to find the index of the leftmost <code>target</code> in the array</strong>. Initially, consider implementing this through the steps shown in Figure 10-5:</p>
|
||||
<p>The problem requires inserting the target element at the leftmost position, <strong>so we need to find the index of the leftmost <code>target</code> in the array</strong>. A straightforward initial approach is to follow the steps shown in Figure 10-5:</p>
|
||||
<ol>
|
||||
<li>Perform binary search to obtain the index of any <code>target</code>, denoted as <span class="arithmatex">\(k\)</span>.</li>
|
||||
<li>Starting from index <span class="arithmatex">\(k\)</span>, perform linear traversal to the left, and return when the leftmost <code>target</code> is found.</li>
|
||||
@@ -4652,10 +4652,10 @@
|
||||
<p align="center"> Figure 10-5 Linear search for insertion point of duplicate elements </p>
|
||||
|
||||
<p>Although this method works, it includes linear search, resulting in a time complexity of <span class="arithmatex">\(O(n)\)</span>. When the array contains many duplicate <code>target</code> elements, this method is very inefficient.</p>
|
||||
<p>Now consider extending the binary search code. As shown in Figure 10-6, the overall process remains unchanged: calculate the midpoint index <span class="arithmatex">\(m\)</span> in each round, then compare <code>target</code> with <code>nums[m]</code>, divided into the following cases:</p>
|
||||
<p>Now consider extending the binary search code. As shown in Figure 10-6, the overall process remains unchanged: in each iteration, we first compute the midpoint index <span class="arithmatex">\(m\)</span>, then compare <code>target</code> with <code>nums[m]</code>, leading to the following cases:</p>
|
||||
<ul>
|
||||
<li>When <code>nums[m] < target</code> or <code>nums[m] > target</code>, it means <code>target</code> has not been found yet, so use the ordinary binary search interval narrowing operation to <strong>make pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span> approach <code>target</code></strong>.</li>
|
||||
<li>When <code>nums[m] == target</code>, it means elements less than <code>target</code> are in the interval <span class="arithmatex">\([i, m - 1]\)</span>, so use <span class="arithmatex">\(j = m - 1\)</span> to narrow the interval, thereby <strong>making pointer <span class="arithmatex">\(j\)</span> approach elements less than <code>target</code></strong>.</li>
|
||||
<li>When <code>nums[m] < target</code> or <code>nums[m] > target</code>, it means <code>target</code> has not been found yet, so use the standard interval-shrinking operation of binary search to <strong>move pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span> closer to <code>target</code></strong>.</li>
|
||||
<li>When <code>nums[m] == target</code>, it means elements less than <code>target</code> are in the interval <span class="arithmatex">\([i, m - 1]\)</span>, so use <span class="arithmatex">\(j = m - 1\)</span> to shrink the interval, thereby <strong>moving pointer <span class="arithmatex">\(j\)</span> closer to elements less than <code>target</code></strong>.</li>
|
||||
</ul>
|
||||
<p>After the loop completes, <span class="arithmatex">\(i\)</span> points to the leftmost <code>target</code>, and <span class="arithmatex">\(j\)</span> points to the first element less than <code>target</code>, <strong>so index <span class="arithmatex">\(i\)</span> is the insertion point</strong>.</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:8"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label><label for="__tabbed_2_7"><7></label><label for="__tabbed_2_8"><8></label></div>
|
||||
@@ -4688,7 +4688,7 @@
|
||||
</div>
|
||||
<p align="center"> Figure 10-6 Steps for binary search insertion point of duplicate elements </p>
|
||||
|
||||
<p>Observe the following code: the operations for branches <code>nums[m] > target</code> and <code>nums[m] == target</code> are the same, so the two can be merged.</p>
|
||||
<p>Observe the following code: the branches <code>nums[m] > target</code> and <code>nums[m] == target</code> perform the same operation, so they can be merged.</p>
|
||||
<p>Even so, we can still keep the conditional branches expanded, as the logic is clearer and more readable.</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:13"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><input id="__tabbed_3_4" name="__tabbed_3" type="radio" /><input id="__tabbed_3_5" name="__tabbed_3" type="radio" /><input id="__tabbed_3_6" name="__tabbed_3" type="radio" /><input id="__tabbed_3_7" name="__tabbed_3" type="radio" /><input id="__tabbed_3_8" name="__tabbed_3" type="radio" /><input id="__tabbed_3_9" name="__tabbed_3" type="radio" /><input id="__tabbed_3_10" name="__tabbed_3" type="radio" /><input id="__tabbed_3_11" name="__tabbed_3" type="radio" /><input id="__tabbed_3_12" name="__tabbed_3" type="radio" /><input id="__tabbed_3_13" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">Python</label><label for="__tabbed_3_2">C++</label><label for="__tabbed_3_3">Java</label><label for="__tabbed_3_4">C#</label><label for="__tabbed_3_5">Go</label><label for="__tabbed_3_6">Swift</label><label for="__tabbed_3_7">JS</label><label for="__tabbed_3_8">TS</label><label for="__tabbed_3_9">Dart</label><label for="__tabbed_3_10">Rust</label><label for="__tabbed_3_11">C</label><label for="__tabbed_3_12">Kotlin</label><label for="__tabbed_3_13">Ruby</label></div>
|
||||
<div class="tabbed-content">
|
||||
@@ -4954,10 +4954,10 @@
|
||||
</div>
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>The code in this section all uses the "closed interval" approach. Interested readers can implement the "left-closed right-open" approach themselves.</p>
|
||||
<p>The code in this section uses the "closed interval" approach throughout. Interested readers can implement the "left-closed, right-open" approach themselves.</p>
|
||||
</div>
|
||||
<p>Overall, binary search is simply about setting search targets for pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span> separately. The target could be a specific element (such as <code>target</code>) or a range of elements (such as elements less than <code>target</code>).</p>
|
||||
<p>Through continuous binary iterations, both pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span> gradually approach their preset targets. Ultimately, they either successfully find the answer or stop after crossing the boundaries.</p>
|
||||
<p>Overall, binary search is simply a matter of setting separate search targets for pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span>. The target may be a specific element (such as <code>target</code>) or a range of elements (such as elements less than <code>target</code>).</p>
|
||||
<p>With each iteration of binary search, pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span> gradually approach their preset targets. Ultimately, they either find the answer or stop after crossing the boundary.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
@@ -5004,7 +5004,7 @@ aria-label="Footer"
|
||||
<a
|
||||
href="../binary_search_edge/"
|
||||
class="md-footer__link md-footer__link--next"
|
||||
aria-label="Next: 10.3 Binary Search Edge Cases"
|
||||
aria-label="Next: 10.3 Binary Search Boundaries"
|
||||
rel="next"
|
||||
>
|
||||
<div class="md-footer__title">
|
||||
@@ -5012,7 +5012,7 @@ aria-label="Footer"
|
||||
Next
|
||||
</span>
|
||||
<div class="md-ellipsis">
|
||||
10.3 Binary Search Edge Cases
|
||||
10.3 Binary Search Boundaries
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
|
||||
Reference in New Issue
Block a user