在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大 O 符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。
常见的时间复杂度量级有:
无论代码执行了多少行,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是 O(1),如:3B
int i = 1;int j = 2;++i;j++;int m = i + j;
消耗的时间是随着 n 的变化而变化的,因此这类代码都可以用 O(n)来表示它的时间复杂度。
for (i = 0; i <= n; ++i) {j = i;j++;}
如果 ax =N(a>0,且 a≠1),那么数 x 叫做以 a 为底 N 的对数,记作 x=logaN,读作以 a 为底 N 的对数,其中 a 叫做对数的底数,N 叫做真数。 一般地,函数 y=logaX(a>0,且 a≠1)叫做对数函数,也就是说以幂(真数)为自变量,指数为因变量,底数为常量的函数,叫对数函数。 其中 x 是自变量,函数的定义域是(0,+∞),即 x>0。它实际上就是指数函数的反函数,可表示为 x=ay。因此指数函数里对于 a 的规定,同样适用于对数函数。
int i = 1;while(i<n) {i = i * 2;}
平方阶 O(n2) 就更容易理解了,如果把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n2) 了。
数据结构的存储方式只有两种:数组(顺序存储)和链表(链式存储)。
数组由于是紧凑连续存储,可以随机访问,通过索引快速找到对应元素,而且相对节约存储空间。但正因为连续存储,内存空间必须一次性分配够,所以说数组如果要扩容,需要重新分配一块更大的空间,再把数据全部复制过去,时间复杂度 O(N);而且你如果想在数组中间进行插入和删除,每次必须搬移后面的所有数据以保持连续,时间复杂度 O(N)。
链表因为元素不连续,而是靠指针指向下一个元素的位置,所以不存在数组的扩容问题;如果知道某一元素的前驱和后驱,操作指针即可删除该元素或者插入新元素,时间复杂度 O(1)。但是正因为存储空间不连续,你无法根据一个索引算出对应元素的地址,所以不能随机访问;而且由于每个元素必须存储指向前后元素位置的指针,会消耗相对更多的储存空间。
单向链表
双向链表
循环链表
树的遍历方式
其实算法方面在前端的实际项目中涉及得并不多,但还是需要精通一些基础性的算法,一些公司还是会有这方面的需求和考核,建议大家还是需要稍微准备下,这属于加分题。
function bubleSort(arr) {var len = arr.length;for (let outer = len; outer >= 2; outer--) {for (let inner = 0; inner <= outer - 1; inner++) {if (arr[inner] > arr[inner + 1]) {[arr[inner], arr[inner + 1]] = [arr[inner + 1], arr[inner]];}}}return arr;}
function selectSort(arr) {var len = arr.length;for (let i = 0; i < len - 1; i++) {for (let j = i; j < len; j++) {if (arr[j] < arr[i]) {[arr[i], arr[j]] = [arr[j], arr[i]];}}}return arr;}
function insertSort(arr) {for (let i = 1; i < arr.length; i++) {//外循环从1开始,默认arr[0]是有序段for (let j = i; j > 0; j--) {//j = i,将arr[j]依次插入有序段中if (arr[j] < arr[j - 1]) {[arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];} else {break;}}}return arr;}
function quickSort(arr) {if (arr.length <= 1) {return arr; //递归出口}var left = [],right = [],current = arr.splice(0, 1);for (let i = 0; i < arr.length; i++) {if (arr[i] < current) {left.push(arr[i]); //放在左边} else {right.push(arr[i]); //放在右边}}return quickSort(left).concat(current, quickSort(right));}
希尔排序:不定步数的插入排序,插入排序
口诀: 插冒归基稳定,快选堆希不稳定
稳定性: 同大小情况下是否可能会被交换位置, 虚拟 dom 的 diff,不稳定性会导致重新渲染;
初始在第一级,到第一级有 1 种方法(s(1) = 1),到第二级也只有一种方法(s(2) = 1), 第三级(s(3) = s(1) + s(2))
function cStairs(n) {if (n === 1 || n === 2) {return 1;} else {return cStairs(n - 1) + cStairs(n - 2);}}
参考十大经典排序算法
局部最优解法
分成多个小模块,与原问题性质相同
发现原先选择不优时,退回重新选择
每个状态都是过去历史的一个总结
有 n 个硬币,其中 1 个为假币,假币重量较轻,你有一把天平,请问,至少需要称多少次能保证一定找到假币?
三等分算法:
如从海量数字中寻找最大的 k 个,这类问题我们称为 TOPK 问题,通常使用堆来解决: