前端需要算法吗?别想太多,肯定的!!!什么是算法?你以为的算法就是排序、选择排序、快速排序、归并排序、宽深度搜索、动态规划……然而,算法其实指的是一种解决实际问题的方法。有很多方法可以解决同样的问题。比如循环输出一个数组,可以有for、forin、forof、map、forEach等,不同的实现方式会体现出不同的性能。这些性能通常用执行时间来表示。执行时间越短,性能越好。到目前为止,我可以告诉你的是,在上述循环中,原生for循环的性能是最好的。下面都是非常非常非常简单的算法知识!!你千万不要害怕!!数组和链表数组是算法中最常用的数据结构。给定一串数组,您可以根据索引快速找到该元素。你可能知道时间复杂度O(n),我们称之为bigOnotation,是大写字母O,不是数字0,别误会。通常大O代表算法的最坏情况。数组O(时间复杂度)读取O(1)写入O(n)删除O(n)数组的大O很容易理解。读的时候,最坏情况是1次,因为数组在内存中是连续的地址(计算机知识),直接根据地址(索引)就可以找到那个元素。写入时,如果在数组末尾压入新元素,则现有元素的地址不需要改变,但如果在数组头部压入新元素,则必须将所有现有元素的地址添加1,即需要移动n个元素,所以大O为n。删除时,与插入相同。最好的情况是删除最后一个元素,复杂度为1。最坏的情况是删除第一个元素。所有剩下的元素都需要减1,也就是需要移动n次。.也许你会发现上面的不对劲。删除的时候不是移动n-1个元素吗?事实上,这是我们需要知道的。大O表示法只描述了次数和数据量之间的线性关系。我们关注的是线性变化的规律,不关心影响的小小。链表链表比较复杂,我们这里只关心链表的一些特性。链表和数组一样,通常存在于内存中。链表可以存在于内存中的任何地方,而且不一定是连续的。你可能不理解这句话。比如你有一个8G的内存条,可能分配给多个应用,你创建一个长度为10的数组,那么系统会分配10个连续的内存地址给你使用。至于链表,假设你有10条数据,可以通过链表插入到内存的空闲地址位置,中间可能被其他数据隔开。这类似于转学生来到你的班级并插入任何空缺。链表还有一个重要的特点就是它的读取必须从头开始遍历,因为只有当前元素位置才有指向下一个元素的指针!!你不能直接读取第N个元素!链表O(时间复杂度)读O(n)写O(1)删除O(1)你会发现链表的读大O是n,也就是说最坏情况下,如果那需要要读取的元素刚好在链表的末尾,那么就需要遍历整个链表。写入和删除都是O(1),这跟链表的特性有关。你可以在链表的任意一个指针处写入新元素和删除元素,但只需要将前一个元素的指针指向新元素或下一个元素即可。链表没有地址的概念,所以不需要移动地址。形象地表达数组和链表在内存中的特性。如果你觉得上面的文字很抽象,你可以看看下表。假设这段内存中有8个内存地址,现在都空闲了。当你创建一个长度为2的内存数组newArray(2)时,系统会为数组分配2个内存地址,可能是地址0和1。然后继续创建数组newArray(1)长度为1,系统会分配1个内存地址给数组。假设是地址4。现在整个内存被2个数组分割。单个数组的内存必须是连续的。是的,不同阵列之间不需要连续性。此时,您创建另一个包含3个元素的链表。现在地址2、3、5、6和7都是免费的。假设链表的第一个元素是2,那么下一个元素可以指向任意一个空闲的。地址,比如3,当到达地址3时,地址4已经被数组的元素占用了,不用担心,链表可以把指针指向地址5,所以链表的第三个元素存放在address上5、这样,你是不是对数组和链表的基本特性有了更清晰的认识?01234567组合数据结构数组和链表也可以组合成一个复合数据结构,叫做“链群结构”,不是Electra,不是Oedipus,而是链群!作为前端,其实只需要考虑数组相关的基本算法,还有各种性能提升的技巧。RecursionofSimpleAlgorithms我问算法工程师如何学好算法。他建议我先了解一下河内塔。这是一款小朋友都可以玩的游戏,里面用到了递归的思想。不过我这里不说汉诺塔,而是先从递归的简单实现说起。之前也写过递归的文章,ES6也有尾递归优化的介绍。但是递归的思想不仅仅应用在阶乘算法中,在各种需要递归的场景中,尤其是在函数式编程中,递归越来越重要。倒计时函数的递归实现下面的倒计时函数使用了递归,使用了尾递归优化。尾递归优化你可能不了解,我觉得你可以看一下尾递归优化函数的特点countdown(i){if(i<=0)returnconsole.log(i)setTimeout(()=>{returncountdown(i-1)},1000)}countdown(10)阶乘的递归实现什么是阶乘?n!表示1X2X3X...Xnfunctiont(i,s=1){if(i<=0)returnss*=ireturnt(i-1,s)}consts=t(5)console.log(s)递归分治的思想是实现数组元素的求和需求。假设您有一个由数字组成的数组。现在您需要编写一个函数来对所有元素求和,例如[2,4,6]。这里不仅有递归的思想,还有一种叫做分而治之的思想。分而治之的思想分为两步。一是摸清基线条件。第二个是每次调用递归都离基线条件更近了一步。那么数组[2,4,6]的基准条件是什么?其实是一种危急情况,比如数组元素为空时的[],或者数组只剩下一个元素时的[2]。这个基线的作用是什么?当递归到达基线时,返回结果而无需进一步递归。下面的代码其实是按照这么一个步骤执行的,[2,4]+6=>[2]+4+6=>2+4+6,不断的对数组进行拆分求和,直到数组的基线条件为达到,此时返回添加的总和。非尾递归优化函数add_1(arr,len=arr.length,sum=arr[len-1]){if(len<=1)returnsumreturnsum+add_1(arr.slice(0,len-1))}constr=add_1([2,4,6])console.log(r)//12尾递归优化函数add_2(arr,len=arr.length,sum=arr[len-1]){if(len<=1)返回总和len=arr。切片(0,长度-1)。lengthsum+=arr[len-1]returnadd_2(arr.slice(0,len-1),len,sum)}constp=add_2([2,4,6])console.log(p)//12小结学习算法是一个漫长的过程。第一次学网页设计的时候,div是个什么东西,要花半年多的时间。后来css的学习时间比较长,js的学习从开始一直持续到现在。正则学习一开始也是很痛苦的。最后,轮到算法了。!
