其实算法方面在前端的实际项目中涉及得并不多,但还是需要精通一些基础性的算法,一些公司还是会有这方面的需求和考核,建议大家还是需要稍微准备下,这属于加分题。
- 栈,后进后出,push,pop
- 队列,先进先出,push,shift
- 链表,结点,对元素的内存地址一无所知(每一个结点的结构都包括了两部分的内容,数据域和指针域
五大算法
- 贪心算法: 局部最优解法
- 分治算法: 分成多个小模块,与原问题性质相同
- 动态规划: 每个状态都是过去历史的一个总结
- 回溯法: 发现原先选择不优时,退回重新选择
- 分支限界法
基础排序算法
// 冒泡排序: 两两比较
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;
}
高级排序算法
快速排序
- 选择基准值(base),原数组长度减一(基准值),使用 splice
- 循环原数组,小的放左边(left数组),大的放右边(right数组);
- concat(left, base, right)
- 递归继续排序 left 与 right
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)
}
}
斐波那契数列:
function f(n){
if(n===0){ return 0}
else if(n===1){return 1}
else {
let fn1 = 0,fn2=1,fnx=0;
for(let i = 0;i<n-1;i++){
let newFn = fn2;
fnx=fn1+fn2;
fn1=fn2;
fn2=fnx;
}
return fnx
}
}
递归算法:
function fib(count){
let count = parseInt(count);
if(isNaN(count) || count <=0){return 0}
function fn(count){
if(count <= 2){return 1}
return fn(count-1)+fn(count-2)
}
return fn(count)
}
求前20个数字
let arr = [1,2];
for(let i = 3;i<20;i++){
arr[i] = arr[i-1]+arr[i-2]
}
for(let i = 1;i<arr.length;i++){
console.log(arr[i])
}
天平找次品
有n个硬币,其中1个为假币,假币重量较轻,你有一把天平,请问,至少需要称多少次能保证一定找到假币?
三等分算法:
将硬币分成3组,随便取其中两组天平称量
- 平衡,假币在未上称的一组,取其回到 1 继续循环
- 不平衡,假币在天平上较轻的一组, 取其回到 1 继续循环
二叉树-递归函数(递归式,递归边界)
/ 先序遍历的遍历实现
// 所有遍历函数的入参都是根据结点对象
function preorder(root) {
// 递归边界,root为空
if(!root) {
return
}
// 输出当前遍历的结点值
console.log('当前遍历的结点值' + root.val);
// 递归遍历左子树:
preorder(root.left);
// 递归遍历右子树:
preorder(root.right);
}
// 中序遍历,左子树,根结点,右子树
function inorder(root) {
if(!root) {
return
}
// 递归遍历左子树
inorder(root.left);
// 输出当前遍历的结点值
console.log('当前遍历的结点是', root.val);
// 递归遍历右子树
inorder(root.right);
}
// 后序遍历:左子树,右子树,根结点
function postorder(root) {
if(!root) {
return
}
// 递归遍历左子树
postorder(root.left)
// 递归遍历右子树
postorder(root.right)
// 输出当前遍历的结点值
console.log('当前遍历的结点值是:'+root.val)
}
Nodejs
什么是nodejs
Nodejs是服务器端的一门技术,它是基于Google V8 JavaScript引擎而开发的,用来开发可扩展的服务端程序。
为什么要用nodejs
Nodejs会让我们的编程工作变得简单,它主要包含以下几个好处:
执行快速,永远不会阻滞,独立的异步处理机制,避免了并行带来的问题。而JavaScript又是通用的编程语言。
Nodejs有哪些特点
Nodejs是单线程的,但是有很高的可扩展性,使用JavaScript作为主流编程语言,使用的是异步处理机制和事件驱动,处理高效。
为什么nodejs是单线程的
Nodejs使用的是单线程,通过异步处理的方式,可以处理大量的数据吞吐量,从而有更好的性能和可扩展性。
什么是回调函数
回调函数是指一个函数作为参数传入另一个函数,这个函数会被在某个时机调用。
什么是回调地狱
回调地狱是由嵌套的回调函数导致的,这样的机制会导致有些函数无法到达,并且很难维护。
如何阻止回调地狱
有三种方法,对每个错误都要处理到,保证代码的贯通,程序代码模块化。
Node 的 Event Loop: 6个阶段
timer 阶段: 执行到期的
setTimeout / setInterval队列回调I/O 阶段: 执行上轮循环残流的
callbackidle, prepare
poll: 等待回调
- 执行回调
执行定时器
- 如有到期的
setTimeout / setInterval, 则返回 timer 阶段- 如有
setImmediate,则前往 check 阶段check
- 执行
setImmediateclose callbacks
Nodejs和ajax的区别是什么
Nodejs和ajax都是通过JavaScript来表现的,但是它们的目的是不同的。Ajax是设计用来动态的更新页面的某个区域,从而不需要更新整个页面。Nodejs是用来开发客户服务器类型应用的。
Nodejs中的chaining是什么
Chaining是指从一个数据流到另一个数据流的链接,从而实现多个流操作。
什么是streams,有哪些类型
流的概念是不间断的,它可以不间断的从某个地方读取数据,或者从某个地方写入数据。流数据大致有4中类型:可读、可写、即可读又可写、转化。
退出代码是什么,有哪些退出代码
退出代码是指中断nodejs运行时返回的代码。退出代码有:
Unused , Uncaught fatal exception , fatal error , non function internal exception handler ,
Internal exception handler run time failure , internal JavaScript evaluation failure
什么是globals
有三个global的关键字。Global代表的是最上层的命名空间,用来管理所有其他的全局对象。Process是一个全局对象,可以把异步函数转化成异步回调,它可以在任何地方被访问,它主要是用来返回系统的应用信息和环境信息。Buffer是用来处理二进制数据的类。
Angular js和nodejs区别是什么
Angularjs是网络应用开发框架,而nodejs是一个实时系统。
Nodejs是如何支持多处理器平台的
Cluster模块是用来支持这方面的,它可以允许多个nodejs工作进程运行在相同的端口上。