一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
1、前端真的需要学习算法吗?
算法已经成为了前端面试“必不可少”的一部分,虽然很卷,但是大部分人还是需要简单学习一下的。因为如果你会一些算法,在一些应用上能够想到更多更优的解决方案,让我们的程序更好更快。
2、学习算法的基本功
学习任何知识,我们都需要打好基础。而学习算法的基础就需要你弄懂什么是复杂度,什么是时间复杂度,什么是空间复杂度。
3、什么是复杂度?
1、复杂度就是程序执行的时候所需要的计算量和内存空间。
这里的计算量就是时间复杂度;
- 这里的内存空间就是空间复杂度,而这里的内存空间和你代码的简洁程度之间的关系是不大的。
- 这里的复杂度和代码的简洁程度是关系不大的,它的复杂度指的是计算机底层处理程序的时候所需要消耗的资源,包括时间和空间资源。打个比方,有的程序写的非常简单,代码量非常少,但是一执行,发现浏览器奔溃了;另外一种情况就是代码量相对比较大,但是程序执行的速度很快,这两种情况就形成了鲜明的对比。
2. 复杂度指的是数量级,而不是具体的数字。
- 为什么是数量级而不是具体数字呢?因为现在程序的运行经过计算机的层层处理,程序占用的内存等已经没有办法精确算出,或者说估算出这个空间的占用是一个非常费时费力的事情,远远不如利用数量级进行描述更加方便。我们总不能为了学习算法,先去学习大量数学知识,先成为一个数学家吧?在举个例子,细菌和你自己进行比较,很明显不在一个数量级吧,大肠杆菌和肺炎球杆菌都是细菌,很明显是一个数量级的,作为一个普通人没必要一定要计算出每个细菌的大小吧?
3. 复杂度一般针对的是一道题,而不是一套系统。
- 为什么这么说呢?举个例子,你能说出“两数之和”这道题目不同就题思路的复杂度,但是你没办法说出leetcode网站或者掘金网站的复杂度吧?每个网站或者每个系统都是由很多的函数或者算法组成,多个算法进行了组合,你就没办法再准确的计算出复杂度,甚至都无法估算。
4、常见复杂度
1. 时间复杂度
- O(1):固定次数就够,不随着输入的数据量而发生改变,比如输入变量为1和100时,执行次数都是1;
代码演示:
function(arr,key){
... ;
console.log(arr[key])
}
这里的变量为一个数组和一个下标,无论数组长度时多少,这里只执行一次。当然,里边打印console.log(arr[key]+arr[key+1]+arr[key+2])依然是O(1)数量级。
- O(n):和输入的数据量成正相关,比如输入变量为1执行一次,输入变量为10,执行10次;
代码演示:
function(arr){
for(let i=0; i<arr.length; i++){
console.log(i)
}
}
这个时候,只要arr的长度增加1,程序计算的次数就会增加1次
- O(n^2): 和输入的数据量成次方关系增长,比如输入变量为1,执行1次,输入变量为10,执行100次; 代码演示:
function(arr){
for(let i=0; i<arr.length; i++){
for(let j=0; j<arr.length; j++){
console.log(i+j)
}
}
}
这个时候,arr长度为10,打印的数据会成100次,这就是一个平方的关系。
- O(logn):和输入的数据量成对数关系,比如,输入变量为100,执行10次,输入变量为10000,执行100次; 二分搜索一定有某种行为使其时间复杂度为O(logn),这里代码比较复杂,后续再根据具体的算法题目进行备注,如果你想先了解一下,可以点击这里简单了解一下
- O(nlogn):输入变量输入变量的对数,比如输入变量为100,执行次数为1000(100log100)次。
这里就是在循环中嵌套一个二分(O(logn))
function(arr){
for(let i=0; i<arr.length; i++){
//下边需要写二分(O(logn))代码
...
}
}
这里只是简单列举了最常见的时间复杂度,还有其他的时间复杂度,比如说O(n^3)...
2. 空间复杂度
- O(1):有限的、可数的空间
代码演示:
function(arr){
const a = arr[1];
const b = arr[2];
}
这里的变量为一个数组,函数体中不要写循环,是一个静态程序,无论arr如何改变,函数体中变量的数量是不变的,也就是说占用内存空间是一定的。
- O(n):和输入的数据量相同的空间,或者说随着输入的数据量变大,其会线性变大
代码演示:
function(arr){
const newArr = [];
for(let i=0; i<arr.length; i++){
newArr[i] = arr[i]
}
}
这里的变量为一个数组,函数体中写循环,函数体中新的数组长度就影响了内存占用空间,也就是说变量arr增加,那么新数组占用的空间也会增加,而且是等量增加。 同样的大家可以思考一下:O(n^2),O(logn),O(n*logn)的常见情景有哪些呢?
总结
对于算法复杂度,前端是一个重时间轻空间的职业(要求执行速度要快比较重视时间复杂度,一般内存是够用的,所以相对于时间复杂度而言会看的轻一点),所以在我们写程序的时候要更加重视时间复杂度,甚至在写相关代码的时候养成分析复杂度的习惯。