style fix
This commit is contained in:
112
Html/apps/static/68bacdfadf5aeae0912f7f18-第四章:查询-二分查找.html
Normal file
112
Html/apps/static/68bacdfadf5aeae0912f7f18-第四章:查询-二分查找.html
Normal file
@@ -0,0 +1,112 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Document</title>
|
||||
<!-- 你的其他样式 -->
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||
<script>
|
||||
MathJax.config = {
|
||||
tex: {
|
||||
inlineMath: [['$', '$'], ['\(', '\)']]
|
||||
},
|
||||
svg: {
|
||||
fontCache: 'global'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>二分查找</h1>
|
||||
<h2>二分查找</h2>
|
||||
<h3>二分查找的原理</h3>
|
||||
<p>二分查找是一个基础但很重要的知识点,也是一种特殊的分治,为以后许多高级的数据结构与算法铺垫。</p>
|
||||
<p>下面是一个用二分的简单场景:</p>
|
||||
<p>假设小明从0到1000之间选择了一个数字但不告诉你,你可以不断猜测这个数,每次猜测小明会告知你的猜测得过大还是过小,问最多几次就一定能猜中?</p>
|
||||
<p>答案是利用二分查找的原理,猜测11次即可。</p>
|
||||
<ol>
|
||||
<li>对于0到1000的答案备选区,猜测中位数500,假设过小,</li>
|
||||
<li>则对于501到1000的答案备选区,猜测750,假设过大</li>
|
||||
<li>则对于501到749的答案备选区,猜测625,假设过小,</li>
|
||||
<li>则对于626到749区间......</li>
|
||||
<li>(688-749)</li>
|
||||
<li>(718-749)</li>
|
||||
<li>(734-749)</li>
|
||||
<li>(742-749)</li>
|
||||
<li>(746-749)</li>
|
||||
<li>(748-749)</li>
|
||||
<li>(749-749)</li>
|
||||
</ol>
|
||||
<p>在最差的情况下,第11次的答案备选区就一定长度为1了,也就是必然是答案。</p>
|
||||
<p>因此如果序列是有序的,就可以通过二分查找快速定位所需要的数据。</p>
|
||||
<h4>例题</h4>
|
||||
<p>对于上面那个题目,如果问题区间是1到4000,最差情况下需要猜测几次?这个值可以怎么迅速地算出来,你可以用时间复杂度的公式建立一下并推导一下么?</p>
|
||||
<h3>练习:二分查找</h3>
|
||||
<p>试试对于下面的题目,用代码实现一下二分查找。</p>
|
||||
<h4>题目:有序数组寻址</h4>
|
||||
<p>给出一个长度为n的有序数组(从小到大),有q次询问,对于每次询问,输出指定数在数组中的下标。如果不存在则输出-1。</p>
|
||||
<h5>输入</h5>
|
||||
<p>第一行一个整数n。(1<=n<=10^5)</p>
|
||||
<p>第二行n个用空格分开的整数ai。(0<=ai<=10^8)</p>
|
||||
<p>第三行一个整数q,表示询问的次数。(1<=q<=10^4)</p>
|
||||
<p>后q行,每行一个整数b,表示询问的数。(0<=b<=10^8)</p>
|
||||
<h5>输出</h5>
|
||||
<p>q行,每行一个整数,对应每次询问的返回结果</p>
|
||||
<h5>提示:</h5>
|
||||
<p>完成代码后,通知Agent进行评测。</p>
|
||||
<p>如果你还不完全会这个算法,询问Agent获取提示并进行学习。</p>
|
||||
<h3>二维二分查找</h3>
|
||||
<h4>二分查找的直觉</h4>
|
||||
<p>通过之前的原理和实现,二分查找本质上是通过取中的方式,尽可能排除多(一半)的备选数。
|
||||
<br>
|
||||
为进一步理解,除了序列,本节我们来尝试一下在矩阵(二维数组)上进行分治和查找。</p>
|
||||
<h4>问题建模</h4>
|
||||
<p>给出一个n*n的矩阵,其中每一行都是一个从小到大的序列,每一列都是从小到大的序列。从中找到指定的一个数target。</p>
|
||||
<h5>例</h5>
|
||||
<p>[
|
||||
[1, 2, 4, 5]
|
||||
[2, 5, 7, 11]
|
||||
[3, 8, 10, 12]
|
||||
[4, 10, 17, 20]
|
||||
]
|
||||
从中找到"8"这个数。</p>
|
||||
<h5>线性做法</h5>
|
||||
<p>这里先介绍线性做法。
|
||||
一维序列的线性做法就是逐个比对一下,
|
||||
二维做法最差是逐个扫描n*n所有的数,可以聪明一些降低到线性成本,称为“楼梯式”查找:</p>
|
||||
<ol>
|
||||
<li>从右上角看一个元素 x = M[r][c]</li>
|
||||
<li>查找与排除
|
||||
a. 若 x > target,则这一列里 x 下方都 ≥ x,更不可能是 target,所以安全地左移(排除一整列)。
|
||||
b. 若 x < target,则这一行里 x 左边都 ≤ x,更不可能是 target,所以安全地下移(排除一整行)。</li>
|
||||
<li>持续直到排除所有行和列,从而找到目标元素或告知找不到。</li>
|
||||
</ol>
|
||||
<p>做法正确性分析,时间复杂度分析。</p>
|
||||
<h4>分治做法:二维二分</h4>
|
||||
<p>接下来试着通过二分的技术,找找复杂度更低的做法。
|
||||
试着回答这些问题,并与AI教师进行讨论:</p>
|
||||
<ol>
|
||||
<li>分解中点在哪里?</li>
|
||||
<li>二分后排除掉的部分是哪些?</li>
|
||||
<li>如何划分子问题?</li>
|
||||
<li>时间复杂度是多少?</li>
|
||||
</ol>
|
||||
<h3>二维二分查找实现</h3>
|
||||
<h4>题目:有序矩阵查找</h4>
|
||||
<p>给出一个 n×n 的矩阵,其中每一行的元素都按照从小到大的顺序排列,每一列的元素也都按照从小到大的顺序排列。现需要判断指定的数 target 是否在该矩阵中,若存在则输出其所在的行下标和列下标(行和列均从 0 开始计数);若不存在则输出 - 1 -1。</p>
|
||||
<h4>输入</h4>
|
||||
<p>第一行一个整数 n。(1<=n<=10^3)
|
||||
接下来 n 行,每行 n 个用空格分开的整数,表示矩阵的元素。
|
||||
最后一行一个整数 target,表示需要查找的数。</p>
|
||||
<h4>输出</h4>
|
||||
<p>一行两个整数,分别表示 target 所在的行下标和列下标,中间用空格隔开。若不存在则输出 - 1 -1。</p>
|
||||
<h4>示例</h4>
|
||||
<p>输入:41 2 4 52 5 7 113 8 10 124 10 17 208
|
||||
输出:2 1</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user