// n 表示数组 array 的长度 int find(int[] array, int n, int x) { int i = 0; int pos = -1; for (; i < n; ++i) { if (array[i] == x) { pos = i; break; } } return pos; }
要查找的变量 x 正好是数组的第一个元素java
若是数组中没有要查找的变量 x,咱们须要把整个数组都遍历一遍python
咱们把每种状况下,查找须要遍历的元素个数累加起来,而后再除以n+1,就能够获得须要遍历的元素个数的平均值,即:算法
咱们知道,要查找的变量 x,要么在数组里,要么就不在数组里。这两种状况对应的几率统计起来很麻烦,为了方便你理解
咱们假设在数组中与不在数组中的几率都为1/2。另外,要查找的数据出如今 0~n-1 这n个位置的几率与时同样的,为1/n。因此,根据几率乘法法则,要查找的数据出如今 0~n0~n-1 中任意位置的几率就是 1/(2n)。编程
所以,前面的推导过程当中存在的最大问题就是,没有将各类状况发生的几率考虑进去,若是咱们把每种状况发生的几率也考虑进来
那么平均时间复杂度的计算过程变成了这样:数组
这个值就是几率论中的加权平均值,也叫作指望值,因此平均时间复杂度的全程也叫加权平均时间复杂度或者指望时间复杂度数据结构
平均复杂度只在某些特殊状况下才会用到,而均摊时间复杂度应用场景它比较特殊、更加有限有限数据结构和算法
// array 表示一个长度为 n 的数组 // 代码中的 array.length 就等于 n int[] array = new int[n]; int count = 0; void insert(int val) { if (count == array.length) { int sum = 0; for (int i = 0; i < array.length; ++i) { sum = sum + array[i]; } array[0] = sum; count = 1; } array[count] = val; ++count; }
一、这段代码实现了一个往数组中插入数据的功能。
二、当数组满了以后也就是代码中的 count == array.length时,咱们用for循环遍历数组求和,并清空数组,将求和以后的sum值放到数组的第一个位置
三、而后再将新的数据插入。但若是数组一开始就有空闲空间,则直接将数据插入数组函数
最理想的状况下,数组中有空闲的空间,咱们只须要将数据插入到数组小表为count的位置就能够了 复杂度为O(1)
最坏的状况下:数组中没有空闲空间;额,咱们须要先作一次数组的遍历求和,而后再将数据插入,因此最坏状况时间复杂度为 O(1)学习
假设数组的长度是 n,根据数据插入的位置的不一样,咱们能够分为n种状况
每种状况的时间复杂度是 O(1)。除此以外,还有一种“额外”的状况,就是在数组没有空闲空间时插入一个数据,这个时候的时间复杂
度是 O(n)。并且,这 n+1 种状况发生的几率同样都是 1/(n+1)。因此,根据加权平均的计算方法,咱们求得得的平均时间复杂度就是:spa
在代码执行的全部复杂度状况中绝大部分是低级别的复杂度,个别状况是高级别复杂度且发生具备时序关系时,能够将个别高级别复杂度均摊到低级别复杂度上。基本上均摊结果就等于低级别复杂度。
均摊时间复杂度就是一种特殊的平均时间复杂度
1.同一段代码在不一样状况下时间复杂度会出现量级差别,为了更全面,更准确的描述代码的时间复杂度,因此引入这4个概念。
2.代码复杂度在不一样状况下出现量级差异时才须要区别这四种复杂度。大多数状况下,是不须要区别分析它们的。
今天你准备去老王家拜访下,惋惜老王的爱人叫他去打个酱油,她告诉你说她限时n分钟🕒给他去买。那么你想着以他家到楼下小卖部来回最多一分钟,
最好的状况
那么 “最好的状况”就是你只用等他一分钟。
最坏的状况:
那么也有可能遇到突发状况,好比说电梯人多吖,路上摔了一胶,天知道他去干了什么,用了n分钟,没办法👐,主上有令,n分钟限时,那这就是“最坏的状况”。
平均时间复杂度:
难点,平均时间复杂度 就是他有多是第1.2.3...n,中的某个分钟回来,那平均就是1+2+3+...n/n,把全部可能出现的状况的时间复杂度相加除以状况数 。
均摊时间复杂度:
均摊的话就是把花时间多的分给花时间少的,获得一个中间值,因此说这就会和平均混淆,我的以为主要仍是概念不一样。假如n是10分钟,那么9分钟分4分钟到1分钟那,8分3给2...,那均摊下来就是5分钟.
代码在不一样状况下复杂度出现量级差异,则用代码全部可能状况下执行次数的加权平均值表示。
2.均摊时间复杂度
两个条件知足时使用:
1)代码在绝大多数状况下是低级别复杂度,只有极少数状况是高级别复杂度;
2)低级别和高级别复杂度出现具备时序规律。均摊结果通常都等于低级别复杂度。
咱们今天学的几个复杂度分析方法,你都掌握了吗?你能够用今天学习的知识,来分析一下下面这个 add() 函数的时间复杂度。
// 全局变量,大小为 10 的数组 array,长度 len,下标 i。 int array[] = new int[10]; int len = 10; int i = 0; // 往数组中添加一个元素 void add(int element) { if (i >= len) { // 数组空间不够了 // 从新申请一个 2 倍大小的数组空间 int new_array[] = new int[len*2]; // 把原来 array 数组中的数据依次 copy 到 new_array for (int j = 0; j < len; ++j) { new_array[j] = array[j]; } // new_array 复制给 array,array 如今大小就是 2 倍 len 了 array = new_array; len = 2 * len; } // 将 element 放到下标为 i 的位置,下标 i 加一 array[i] = element; ++i; }
1. 最好状况时间复杂度为 O(1)
2.最坏状况分析:
最坏状况代码执行的次数跟每次数组的长度有关
第1次调用insert的执行的次数为 n ,
第2次调用insert的执行的次数为 2n ,
第3次调用insert的执行的次数为 2^2 * n
第k次调用insert的执行的次数为 2^(k-1) * n
最坏时间复杂度为 O(n)。
3. 平均状况分析
当每次遇到最坏状况时数组会进行2倍扩容,原数组被导入新数组,虽然数组的长度变大了,可是插入操做落在的区间的长度是同样的,分别是0~len-1, len~(2len-1),....;
插入的状况还是len+1种:0~len-1和插满以后的O(len);因此每次插入的几率是:p= 1/len+1,
最后求出加权平均时间复杂度为 1*p + 2*p+ ▪▪▪ + len*p + len * p = O(1) ;
4. 均摊时间复杂度 O(1)
而均摊复杂度因为每次O(len)的出现都跟着len次O(1),是先后连贯的,于是将O(len)平摊到前len次上,得出平摊复杂度是O(1)
报告老师,我好像走错了教室。
我是一个文科转行过来的菜鸟,刚刚学完Python,基本搞懂了“遍历”、“循环”、“判断”等概念。
您开篇讲的课,我都基本都能明白,也提起了兴趣和信心,准备好好跟您学习。但这两次课听完,我又晕菜了。
想请问一下,若是听不太懂(也能够去掉“太”),须要补哪些课?您能告诉我进入您课程的坡道和垫脚石么?有没有稍低一点年级的资料,让我能够补补课呢?
还请抽时间回答,谢谢
一、你说了刚学完python,可能代码还没写熟练,因此我建议把python书上的全部实例代码都本身敲一遍,默写一遍。学编程,光看不写确定是不行的。
二、等你python代码写熟练了,你能够再开始学我这个专栏。 由于你没有数据结构和算法的基础,因此我建议,配合着《大话数据结构》《算法图解》两本书一块来学习。
三、学习这个专栏的过程当中,你能够把我讲到的数据结构和算法都用python代码实现一遍,若是实现不了,能够参照我放在Github上的代码,本身看懂以后,默写一遍。这个步骤很是锻炼你的编程能力,不要忽视!
四、在学习专栏的过程当中,不要一以为看不懂就放弃,师傅领进门,修行靠我的。这里没有葵花宝典同样的捷径。学习还要靠本身。看不懂?那就本身多百度一下,看不懂也能够问问你同窗、同事、学长,用一个星期来看一篇文章,狠下心来,别怕麻烦,不会学不会的。
还有不少时候看不懂,你就硬着头皮看,都看完一遍,就会有感受。以后再等有空了,再来看一遍,慢慢的都懂了。这门课很难,对于初学者来讲,应该是计算机里最难的之一了,因此不要指望轻松就学会,这是不现实的。