This commit is contained in:
by931
2022-09-06 22:30:37 +08:00
parent 66970f3e38
commit 3d6528675a
796 changed files with 3382 additions and 3382 deletions

View File

@@ -193,10 +193,10 @@ function hide_canvas() {
<p><strong>复杂度是衡量代码运行效率的重要度量因素</strong>。在介绍复杂度之前,有必要先看一下复杂度和计算机实际任务处理效率的关系,从而了解降低复杂度的必要性。</p>
<p>计算机通过一个个程序去执行计算任务,也就是对输入数据进行加工处理,并最终得到结果的过程。每个程序都是由代码构成的。可见,编写代码的核心就是要完成计算。但对于同一个计算任务,不同计算方法得到结果的过程复杂程度是不一样的,这对你实际的任务处理效率就有了非常大的影响。</p>
<p>举个例子,你要在一个在线系统中实时处理数据。假设这个系统平均每分钟会新增 300M 的数据量。如果你的代码不能在 1 分钟内完成对这 300M 数据的处理,那么这个系统就会发生时间爆炸和空间爆炸。表现就是,电脑执行越来越慢,直到死机。因此,我们需要讲究合理的计算方法,去通过尽可能低复杂程度的代码完成计算任务。</p>
<p><img src="assets/CgqCHl7CRGiAe-NpAR0S70dSC2M990.gif" alt="1.gif" /></p>
<p><img src="assets/CgqCHl7CRGiAe-NpAR0S70dSC2M990.gif" alt="png" /></p>
<p>那提到降低复杂度我们首先需要知道怎么衡量复杂度。而在实际衡量时我们通常会围绕以下2 个维度进行。<strong>首先,这段代码消耗的资源是什么</strong>。一般而言,代码执行过程中会消耗计算时间和计算空间,那需要衡量的就是时间复杂度和空间复杂度。</p>
<p>我举一个实际生活中的例子。某个十字路口没有建立立交桥时,所有车辆通过红绿灯分批次行驶通过。当大量汽车同时过路口的时候,就会分别消耗大家的时间。但建了立交桥之后,所有车辆都可以同时通过了,因为立交桥的存在,等于是消耗了空间资源,来换取了时间资源。</p>
<p><img src="assets/CgqCHl7CRMaAO_oEAJfz6fjfMNQ403.gif" alt="2.gif" /></p>
<p><img src="assets/CgqCHl7CRMaAO_oEAJfz6fjfMNQ403.gif" alt="png" /></p>
<p><strong>其次,这段代码对于资源的消耗是多少</strong>。我们不会关注这段代码对于资源消耗的绝对量,因为不管是时间还是空间,它们的消耗程度都与输入的数据量高度相关,输入数据少时消耗自然就少。为了更客观地衡量消耗程度,我们通常会关注时间或者空间消耗量与输入数据量之间的关系。</p>
<p>好,现在我们已经了解了衡量复杂度的两个纬度,那应该如何去计算复杂度呢?</p>
<p><strong>复杂度是一个关于输入数据量 n 的函数</strong>。假设你的代码复杂度是 f(n),那么就用个大写字母 O 和括号,把 f(n) 括起来就可以了,即 O(f(n))。例如O(n) 表示的是,复杂度与计算实例的个数 n 线性相关O(logn) 表示的是,复杂度与计算实例的个数 n 对数相关。</p>
@@ -209,7 +209,7 @@ function hide_canvas() {
<p>例如,你的代码处理 10 条数据需要消耗 5 个单位的时间资源3 个单位的空间资源。处理 1000 条数据,还是只需要消耗 5 个单位的时间资源3 个单位的空间资源。那么就能发现资源消耗与输入数据量无关,就是 O(1) 的复杂度。</p>
<p>为了方便你理解不同计算方法对复杂度的影响,我们来看一个代码任务:对于输入的数组,输出与之逆序的数组。例如,输入 a=[1,2,3,4,5],输出 [5,4,3,2,1]。</p>
<p>先看<strong>方法一</strong>,建立并初始化数组 b得到一个与输入数组等长的全零数组。通过一个 for 循环,从左到右将 a 数组的元素,从右到左地赋值到 b 数组中,最后输出数组 b 得到结果。</p>
<p><img src="assets/Ciqc1F7CRP6ARwDTAGHL-opG6Bk835.gif" alt="3.gif" /></p>
<p><img src="assets/Ciqc1F7CRP6ARwDTAGHL-opG6Bk835.gif" alt="png" /></p>
<p>代码如下:</p>
<pre><code>public void s1_1() {
int a[] = { 1, 2, 3, 4, 5 };
@@ -226,7 +226,7 @@ function hide_canvas() {
<p>这段代码的输入数据是 a数据量就等于数组 a 的长度。代码中有两个 for 循环作用分别是给b 数组初始化和赋值,其执行次数都与输入数据量相等。因此,代码的<strong>时间复杂度</strong>就是 O(n)+O(n),也就是 O(n)。</p>
<p>空间方面主要体现在计算过程中,对于存储资源的消耗情况。上面这段代码中,我们定义了一个新的数组 b它与输入数组 a 的长度相等。因此,空间复杂度就是 O(n)。</p>
<p><strong>接着我们看一下第二种编码方法</strong>,它定义了缓存变量 tmp接着通过一个 for 循环,从 0 遍历到a 数组长度的一半(即 len(a)/2。每次遍历执行的是什么内容就是交换首尾对应的元素。最后打印数组 a得到结果。</p>
<p><img src="assets/Ciqc1F7CR22AIbSuABc0Rwl-t3w666.gif" alt="4.gif" /></p>
<p><img src="assets/Ciqc1F7CR22AIbSuABc0Rwl-t3w666.gif" alt="png" /></p>
<p>代码如下:</p>
<pre><code>public void s1_2() {
int a[] = { 1, 2, 3, 4, 5 };