mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-28 12:31:51 +08:00
deploy
This commit is contained in:
@@ -3382,21 +3382,21 @@
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="102">10.2 二分查找插入点<a class="headerlink" href="#102" title="Permanent link">¶</a></h1>
|
||||
<p>二分查找不仅可用于搜索目标元素,还具有许多变种问题,比如搜索目标元素的插入位置。</p>
|
||||
<p>二分查找不仅可用于搜索目标元素,还可用于解决许多变种问题,比如搜索目标元素的插入位置。</p>
|
||||
<h2 id="1021">10.2.1 无重复元素的情况<a class="headerlink" href="#1021" title="Permanent link">¶</a></h2>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定一个长度为 <span class="arithmatex">\(n\)</span> 的有序数组 <code>nums</code> 和一个元素 <code>target</code> ,数组不存在重复元素。现将 <code>target</code> 插入到数组 <code>nums</code> 中,并保持其有序性。若数组中已存在元素 <code>target</code> ,则插入到其左方。请返回插入后 <code>target</code> 在数组中的索引。</p>
|
||||
<p>给定一个长度为 <span class="arithmatex">\(n\)</span> 的有序数组 <code>nums</code> 和一个元素 <code>target</code> ,数组不存在重复元素。现将 <code>target</code> 插入数组 <code>nums</code> 中,并保持其有序性。若数组中已存在元素 <code>target</code> ,则插入到其左方。请返回插入后 <code>target</code> 在数组中的索引。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找插入点示例数据" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_example.png" /></a></p>
|
||||
<p align="center"> 图 10-4 二分查找插入点示例数据 </p>
|
||||
|
||||
<p>如果想要复用上节的二分查找代码,则需要回答以下两个问题。</p>
|
||||
<p>如果想复用上一节的二分查找代码,则需要回答以下两个问题。</p>
|
||||
<p><strong>问题一</strong>:当数组中包含 <code>target</code> 时,插入点的索引是否是该元素的索引?</p>
|
||||
<p>题目要求将 <code>target</code> 插入到相等元素的左边,这意味着新插入的 <code>target</code> 替换了原来 <code>target</code> 的位置。也就是说,<strong>当数组包含 <code>target</code> 时,插入点的索引就是该 <code>target</code> 的索引</strong>。</p>
|
||||
<p><strong>问题二</strong>:当数组中不存在 <code>target</code> 时,插入点是哪个元素的索引?</p>
|
||||
<p>进一步思考二分查找过程:当 <code>nums[m] < target</code> 时 <span class="arithmatex">\(i\)</span> 移动,这意味着指针 <span class="arithmatex">\(i\)</span> 在向大于等于 <code>target</code> 的元素靠近。同理,指针 <span class="arithmatex">\(j\)</span> 始终在向小于等于 <code>target</code> 的元素靠近。</p>
|
||||
<p>因此二分结束时一定有:<span class="arithmatex">\(i\)</span> 指向首个大于 <code>target</code> 的元素,<span class="arithmatex">\(j\)</span> 指向首个小于 <code>target</code> 的元素。<strong>易得当数组不包含 <code>target</code> 时,插入索引为 <span class="arithmatex">\(i\)</span></strong> 。</p>
|
||||
<p>因此二分结束时一定有:<span class="arithmatex">\(i\)</span> 指向首个大于 <code>target</code> 的元素,<span class="arithmatex">\(j\)</span> 指向首个小于 <code>target</code> 的元素。<strong>易得当数组不包含 <code>target</code> 时,插入索引为 <span class="arithmatex">\(i\)</span></strong> 。代码如下所示:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -3636,7 +3636,7 @@
|
||||
<p align="center"> 图 10-5 线性查找重复元素的插入点 </p>
|
||||
|
||||
<p>此方法虽然可用,但其包含线性查找,因此时间复杂度为 <span class="arithmatex">\(O(n)\)</span> 。当数组中存在很多重复的 <code>target</code> 时,该方法效率很低。</p>
|
||||
<p>现考虑拓展二分查找代码。如图 10-6 所示,整体流程保持不变,每轮先计算中点索引 <span class="arithmatex">\(m\)</span> ,再判断 <code>target</code> 和 <code>nums[m]</code> 大小关系,分为以下几种情况。</p>
|
||||
<p>现考虑拓展二分查找代码。如图 10-6 所示,整体流程保持不变,每轮先计算中点索引 <span class="arithmatex">\(m\)</span> ,再判断 <code>target</code> 和 <code>nums[m]</code> 的大小关系,分为以下几种情况。</p>
|
||||
<ul>
|
||||
<li>当 <code>nums[m] < target</code> 或 <code>nums[m] > target</code> 时,说明还没有找到 <code>target</code> ,因此采用普通二分查找的缩小区间操作,<strong>从而使指针 <span class="arithmatex">\(i\)</span> 和 <span class="arithmatex">\(j\)</span> 向 <code>target</code> 靠近</strong>。</li>
|
||||
<li>当 <code>nums[m] == target</code> 时,说明小于 <code>target</code> 的元素在区间 <span class="arithmatex">\([i, m - 1]\)</span> 中,因此采用 <span class="arithmatex">\(j = m - 1\)</span> 来缩小区间,<strong>从而使指针 <span class="arithmatex">\(j\)</span> 向小于 <code>target</code> 的元素靠近</strong>。</li>
|
||||
|
||||
Reference in New Issue
Block a user