前端算法大致可以分为几类
递归,动态规划,贪心算法 二分查找
以上内容面试官一般都会结合数组,字符串来考察你对以上知识的掌握程度
这些排序里边主要掌握四个就可以:冒泡、选择、插入、快速
冒泡排序算法
function bubbleSort(arr) {
for(let i = 0,l=arr.length;iarr[j]) {
let tem = arr[i];
arr[i] = arr[j];
arr[j] = tem;
}
}
}
return arr;
}
图文:冒泡排序
选择排序
function selectionSort(arr) {
var len = arr.length;
var minIndex, temp;
for (var i = 0; i < len - 1; i++) {
minIndex = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { // 寻找最小的数
minIndex = j; // 将最小数的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
图文选择排序
插入排序
function insertionSort(arr) {
var len = arr.length;
var preIndex, current;
for (var i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while(preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex+1] = arr[preIndex];
preIndex--;
}
arr[preIndex+1] = current;
}
return arr;
}
图文:插入排序
快速排序
function qSort(arr) {
if (arr.length == 0) {
return [];
}
var left = [];
var right = [];
var pivot = arr[0];
for (var i = 1; i < arr.length; i++) { // 注意这里的起始值,因为有一个作为flag了
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return qSort(left).concat(pivot, qSort(right));
}
图文:快速排序
链表
单向链表的添加:
function insert(newElement, item){
var newNode = new Node(newElement); // 新建一个节点
var current = this.find(item); //找到item的位置(current在js中是引用,类似于C语言指针)
newNode.next = current.next; //将新节点的后继指向item的后继
current.next = newNode; // 修改item节点的后继指向新节点
}
单向链表的删除:
// 首先要找到删除元素的上一个节点
function findPrevious (item) {
var currentNode = this.head;
while (!(currentNode.next === null) && (currentNode.element !== item)) {
return currentNode;
}
}
function remove (item) {
var prevNode = this.findPrevious(item);
var currentNode = this.find(item); // 查找到当前要删除的节点
if (!(prevNode.next === null)) {
prevNode.next = prevNode.next.next; //待删除节点的前驱的后继 指向 原本待删除节点的后继
currentNode.next = null; // 释放节点,防止内存泄漏
}
}
双向列表的添加:
// 插入节点,注意插入的链指向
function insert(newElement, item){
var newNode = new Node(newElement); // 新建一个节点
var current = this.find(item); //找到item的位置
newNode.next = current.next; //将新节点的后继指向item的后继
newNode.previous = current;
current.next = newNode;
if (newNode.next !== null) {
newNode.next.previous = newNode; // 将item原本的位置的前驱指向新节点
}
}
双向链表的删除:
function remove (item) {
var currentNode = this.find(item);
if (!(currentNode === null)) {
currentNode.previous.next = currentNode.next; // 删除节点的前驱的后继,指向删除节点的后继
currentNode.next.previous = currentNode.previous; //删除节点的后继的前驱,指向删除节点的前驱
currentNode.next = null; // 释放节点,防止内存泄漏
currentNode.previous = null;
} else {
currentNode.previous.next = null; // 尾节点的前驱的后继指向null
currentNode.previous = null; // 释放尾节点
}
}
斐波那契数列
//递归方案
function gostair(stair){
if(stair < 2){
return stair;
}
return gostair(stair-1) + gostair(stair -2)
}
//动态规划方案
function gostair(n){
let arr = [];
for(let i = 0; i<=n; i++){
arr[i] = 0;
}
if(n == 1||n==2){
return 1;
}else{
arr[1] = 1;
arr[2] = 2;
for(let j = 3;j<=n;j++){
arr[j] = arr[j-1]+arr[j-2];
}
}
return arr[n-1];
}
//迭代方案(指针移动方案)
function gostair(n){
let first = 1;
let last = 1;
let result = 1;
for(let i=2;i
数组拍平
1.arr.join(',').split(',');
2.
function flat(arr) {
var newarr = [];
return function flatten(arr) {
for(let i = 0;i
}
二分查找(前提是排序完成,最快的查找方法)
function find (arr, item) {
var low = 0; //设定下标
var high = arr.length - 1; // 设定上标
while (high >= low) {
var mid = Math.floor((low + high) / 2); //二分查找的关键
if (arr[mid] === item) {
return mid;
}else if (arr[mid] > item) {
high = mid;
} else if (arr[mid] < item){
low = mid;
} else {
return mid;
}
}
return -1;
}
浅拷贝
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
return c;
}
深拷贝:循环调用浅拷贝
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
用代码实现二叉搜索树,写出相关方法查找最小值。
(左子树上所有结点的值均小于它的根结点的值;右子树上所有结点的值均大于它的根结点的值;
)
//定义节点
function Node(data, left, right) {
this.data = data;
this.left = left;
this.right = right;
}
// 插入值
function insert (data) {
var n = new Node(data, null, null); // 定义一个新节点
if(this.root === null) {
this.root = n;
} else {
var current = this.root;
var parent;
while (true) {
parent = current;
if (data < current.data) {
current = current.left; // 比当前值小就放左边
if (current === null) {
parent.left = n;
break;
}
} else { // 比当前值大就放右边
current = current.right;
if(current === null){
parent.right = n;
break;
}
}
}
}
}
// 找最小值
function getSmallest (root) {
// 一直往左子树上去找,找到没有左节点即找到了最小值
var current = this.root || root;
while (!(current.left === null)) {
current = current.left;
}
return current;
}
函数防抖,函数节流
防抖:debounce 操作结束后等待wait才执行一次。实例:keypress查询,防止点击提交按钮时的多次点击。
function debounce(fun,wait){
var timeout = null;
return function(){
if(timeout != null) clearTimeout(timeout);
timeout = setTimeout(fun,wait);
}
}
如果immediate参数如果为true,则debounce函数会在调用时立刻执行一次function,等待时间内只执行一次
function debounce(fun,wait,immediate){
var timeout;
return function(){
var context = this,args = arguments;
var later = function(){
timeout = null;
if(!immediate) fun.apply(context,args);//immediate为false执行,操作结束后等待wait才执行一次
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later,wait);
if(callNow) fun.apply(context,args);//immediate为true执行,操作开始立即执行,
}
}
节流:throttle 每隔多长时间执行一次函数,与防抖相比,节流函数多了一个 mustRun 属性,代表 mustRun 毫秒内,必然会触发一次 handler 实例:滑动加载图片懒加载
function throttle(fun,wait,mustRun){
var timeout,startTime = new Date();
return function(){
var context = this,args = arguments,curTime = new Date();
clearTimeout(timeout);
if(curTime - startTime >= mustRun){
fun.apply(context,args);//mustRun内必触发一次
startTime = curTime;
}else{
timeout = setTimeout(fun,wait);//每个wait触发一次
}
}
无限分类递归树
function toTree(data) {
// 删除 所有 children,以防止多次调用
data.forEach(function (item) {
delete item.children;
});
// 将数据存储为 以 id 为 KEY 的 map 索引数据列
var map = {};
data.forEach(function (item) {
map[item.id] = item;
});
var val = [];
data.forEach(function (item) {
// 以当前遍历项,的pid,去map对象中找到索引的id
var parent = map[item.pid];
// 好绕啊,如果找到索引,那么说明此项不在顶级当中,那么需要把此项添加到,他对应的父级中
if (parent) {
(parent.children || ( parent.children = [] )).push(item);
} else {
//如果没有在map中找到对应的索引ID,那么直接把 当前的item添加到 val结果集中,作为顶级
val.push(item);
}
});
return val;
}
获取两个时间中的所有年月
function getYearAndMonth(start, end) {
var result = [];
var starts = start.split('-');
var ends = end.split('-');
var staYear = parseInt(starts[0]);
var staMon = parseInt(starts[1]);
var endYear = parseInt(ends[0]);
var endMon = parseInt(ends[1]);
while (staYear <= endYear) {
if (staYear === endYear) {
while (staMon < endMon) {
staMon++;
result.push({year: staYear, month: staMon});
}
staYear++;
} else {
staMon++;
if (staMon > 12) {
staMon = 1;
staYear++;
}
result.push({year: staYear, month: staMon});
}
}
return result;
}