时间复杂度 空间复杂度
时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述。
空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述。
常见的复杂度有以下量级(具体介绍几种其他类似)
常数阶O(1)
对数阶O(logN)
线性阶O(n)
线性对数阶O(nlogN)
平方阶O(n²)
立方阶O(n³)
K次方阶O(n^k)
指数阶(2^n)
常数阶O(N)(没有复杂的结构)例如:
let i = 0;
i++;
console.log(i)
线性阶 例如:
for(let i=0; i<=n; i++) {
...
}
for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的所以时间复杂度为O(N)
平方阶O(n²) 例如:
for(let i=0; i<=n; i++) {
for(let j=0; j<n; j++) {
...
}
}
套了2层n循环,消耗的时间为N*N, 所以它的时间复杂度为O(n乘n),即 O(n²)
对数阶O(logN) 例如:
let i = 1;
while(i<n)
{
i = i * 2;
}
while循环里面,每次都将i乘以2 所以2的x次方等于n,那么x=log2(n) 循环x次之后结束 所以时间复杂度为O(logn)
线性对数阶O(nlogN) 例如:
for(m=1; m<n; m++)
{
i = 1;
while(i<n)
{
i = i * 2;
}
}
数组和链表
特点
数组
1.整个数组占用的内存空间是连续的
2.每个元素占用的内存大小是完全一样的
3.通过下标寻找对应元素效率极高,因此遍历速度快
查找操作O(1) 但是删除、插入操作为O(N) 有没有一种情况 实现删除、插入操作也为O(1)呢?
链表
1.每个元素除了存储数据,需要有额外的内存存储一个引用(地址),来指向下一个元素
2.每个元素占用的内存空间并不要求是连续的
3.往往使用链表的第一个节点(根节点)来代表整个链表
4.长度是可变的,随时可以增加和删除元素
5.插入和删除元素效率极高;
6.通过下标查询链表中的某个节点,效率会很低,所以链表的下标遍历效率很低
查找操作O(N) 但是删除、插入操作为O(1)
JS 数组链表相互转换
let node
let head = {value: ary[0], next: null}
let pnode = head //pnode变量用来保存前一个节点
for(let i = 1; i < ary.length; i++) {
node = {value: ary[i], next:null}
pnode.next = node //将前一个节点的next指向当前节点
pnode = node //将node赋值给pnode
}
function listToarray(head) {
if(!head) {
return []
}
let result = []
let p = head
while(p) {
result.push(p.value)
p = p.next
}
return result
}