首先,一句话,前端学算法有啥用

低情商:好跟后端battle。顺便互相吹吹牛
高情商:提高业务能力。提炼基本功
实际:大厂大公司面试要问,没办法。
工作中:应用场景不多,基本都是后端玩的

那到底学不学

要不要高薪嘛,要你就最好学学,力扣刷刷题。说那么多干啥

那有哪些比较值得刷的算法呢

这里我整理了一些
包括很多其实在高校就会讲的线性表链表二叉树的算法,甚至还有很多别的算法,例如动态规划,贪心算法等等。这些算法往往伴随着面试官考察你的逻辑能力和你的知识深度。

如何用js写算法

(一)链表类
链式结构的创建

1.js没有指针 怎么操作地址,怎么创建链式结构
其实不用想太复杂了,既然js 尤其是现在的ts越来越像java,那这些就不会太复杂
一般链表长这样

一个节点有两条信息

指向链表中下一项的指针或引用(对于单链表)
节点的值
对于我们的节点,我们只需要创建一个函数,该函数接受一个值,并返回一个具有上面两个信息的对象:指向下一个节点的指针和该节点的值。
节点链表将包含五个方法:

push(value): 将值添加到链表的末尾
pop() 弹出链表中的最后一个值
get(index):返回给定索引中的项
delete(index):从给定索引中删除项
isEmpty(): 返回一个布尔值,指示链表是否为空
printList():不是链表的原生方法,它将打印出我们的链表,主要用于调试

构造函数方法:

class Node {constructor(data) {this.data = data;  // 节点的数据域this.prev = null;  // 节点的指针域this.next = null;  // 节点的指针域}
}

只要实现上述的这些方法,一个基本的单链表结构就实现了。

class SingleList {constructor() {this.size = 0;  // 单链表的长度this.head = new Node('head');  // 表头节点this.currNode = '';  // 当前节点的指向}find(item) {}  // 在单链表中寻找item元素insert(item, element) {}  // 向单链表中插入元素remove(item) {}  // 在单链表中删除一个节点append(element) {}  // 在单链表的尾部添加元素findLast() {}  // 获取单链表的最后一个节点isEmpty() {}  // 判断单链表是否为空show() {}  // 显示当前节点getLength() {}  // 获取单链表的长度advance(n, currNode) {}  // 从当前节点向前移动n个位置display() {}  // 单链表的遍历显示clear() {}  // 清空单链表
}

前端中常见常考算法

链表类

前序遍历判断回文链表
利用链表的后续遍历,使用函数调用栈作为后序遍历栈,来判断是否回文

let isPalinDrome = function(head) {let left = head;
function traverse(right) {if (right == null) return true;
let res = traverse(right.next);
res = res && (right.val === left.val);
left = left.next;
return res;
}
return traverse(head);}

通过 快、慢指针找链表中点,然后反转链表,比较两个链表两侧是否相等,来判断是否是回文链表
同时回文链表是很多大厂特别喜欢考的算法题

var isPalindrome = function(head) {// 反转 slower 链表
let right = reverse(findCenter(head));
let left = head;
// 开始比较
while (right != null) {if (left.val !== right.val) {return false;
}
left = left.next;
right = right.next;
}
return true;
}
function findCenter(head) {let slower = head, faster = head;2. 反转链表
3. 合并K个升序链表
while (faster && faster.next != null) {slower = slower.next;
faster = faster.next.next;
}
// 如果 faster 不等于 null,说明是奇数个,slower 再移动一格
if (faster != null) {slower = slower.next;
}
return slower;
}
function reverse(head) {let prev = null, cur = head, nxt = head;
while (cur != null) {nxt = cur.next;
cur.next = prev;
prev = cur;
cur = nxt;
}
return prev;
}

2. 反转链表

* function ListNode(val) {* this.val = val;
* this.next = null;
* }* @param {ListNode} head
* @return {ListNode}var reverseList = function(head) {if (head == null || head.next == null) return head;
let last = reverseList(head.next);
head.next.next = head;
head.next = null;
return last;
};

3. 合并K个升序链表

var mergeKLists = function(lists) {if (lists.length === 0) return null;
return mergeArr(lists);
};
function mergeArr(lists) {if (lists.length <= 1) return lists[0];
let index = Math.floor(lists.length / 2);
const left = mergeArr(lists.slice(0, index))
const right = mergeArr(lists.slice(index));
return merge(left, right);
}
function merge(l1, l2) {if (l1 == null && l2 == null) return null;
if (l1 != null && l2 == null) return l1;
if (l1 == null && l2 != null) return l2;
let newHead = null, head = null;
while (l1 != null && l2 != null) {if (l1.val < l2.val) {if (!head) {newHead = l1;
head = l1;
} else {newHead.next = l1;
newHead = newHead.next;
}
l1 = l1.next;
} else {if (!head) {newHead = l2;
head = l2;
} else {newHead.next = l2;
newHead = newHead.next;
}
l2 = l2.next;
}
}
newHead.next = l1 ? l1 : l2;
return head;
}

K 个一组翻转链表

var reverseKGroup = function(head, k) {let a = head, b = head;
for (let i = 0; i < k; i++) {if (b == null) return head;
b = b.next;
}
const newHead = reverse(a, b);
a.next = reverseKGroup(b, k);
return newHead;
};
function reverse(a, b) {let prev = null, cur = a, nxt = a;
while (cur != b) {nxt = cur.next;
cur.next = prev;
prev = cur;
cur = nxt;
}
return prev;
}

5. 环形链表

var hasCycle = function(head) {if (head == null || head.next == null) return false;
let slower = head, faster = head;
while (faster != null && faster.next != null) {slower = slower.next;
faster = faster.next.next;
if (slower === faster) return true;
}
return false;
}

6. 排序链表(带头结点)

/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function(head) {if (head == null) return null;
let newHead = head;
return mergeSort(head);
};
function mergeSort(head) {if (head.next != null) {let slower = getCenter(head);
let nxt = slower.next;
slower.next = null;
console.log(head, slower, nxt);
const left = mergeSort(head);
const right = mergeSort(nxt);
head = merge(left, right);
}
return head;
}
function merge(left, right) {let newHead = null, head = null;
while (left != null && right != null) {if (left.val < right.val) {if (!head) {newHead = left;
head = left;
} else {newHead.next = left;
newHead = newHead.next;
}
left = left.next;
} else {if (!head) {newHead = right;
head = right;
} else {newHead.next = right;
newHead = newHead.next;
}
right = right.next;
}
}
newHead.next = left ? left : right;
return head;
}
function getCenter(head) {let slower = head, faster = head.next;
while (faster != null && faster.next != null) {slower = slower.next;
faster = faster.next.next;
}
return slower;
}

7. 相交链表(也称十字链表)

Definition for singly-linked list.function ListNode(val) {this.val = val;this.next = null;}@param {ListNode} headA@param {ListNode} headB@return {ListNode}var getIntersectionNode = function(headA, headB) {let lastHeadA = null;
let lastHeadB = null;
let originHeadA = headA;
let originHeadB = headB;
if (!headA || !headB) {return null;
}
while (true) {if (headB == headA) {return headB;
}
if (headA && headA.next == null) {lastHeadA = headA;
headA = originHeadB;
} else {headA = headA.next;
}
if (headB && headB.next == null) {lastHeadB = headB
headB = originHeadA;
} else {headB = headB.next;
}
if (lastHeadA && lastHeadB && lastHeadA != lastHeadB) {return null;
}
}
return null;
}

那些前端用js手搓出来的算法与数据结构(一)链表篇相关推荐

  1. 常见js手撕题及算法总结

    文章目录 实现一下观察者模式 实现一下工厂模式 实现一下单例模式 设计一个lazyMan,实现以下功能: 实现一个简单的EventEmitter 手撕实现原生js的一些方法(call.apply.bi ...

  2. js 数组 实现 完全树_算法和数据结构 | 树状数组(Binary Indexed Tree)

    本文来源于力扣圈子,作者:胡小旭.点击查看原文 力扣​leetcode-cn.com 树状数组或二叉索引树(英语:Binary Indexed Tree),又以其发明者命名为 Fenwick 树.其初 ...

  3. 2020年前端面试之JS手写代码题合集

    2020年前端面试之JS手写代码题合集 预计会有上千道题,后续慢慢补! 1.  写一个把字符串大小写切换的方法 function caseConvert(str){return str.replace ...

  4. 手机端移动端的前端原生js裁剪图片上传

    手机端移动端的前端原生js裁剪图片上传 选择头像时裁剪上传,确保图片是个正方形,不会出现压扁拉伸的现象 效果图 原理很简单,其实就是用canvas截图出来而已,只是要对比例做一下处理. <!-- ...

  5. 用 Node.js 手写一个 DNS 服务器

    DNS 是实现域名到 IP 转换的网络协议,当访问网页的时候,浏览器首先会通过 DNS 协议把域名转换为 IP,然后再向这个 IP 发送 HTTP 请求. DNS 是我们整天在用的协议,不知道大家是否 ...

  6. 前端学习--js.2

    写一个通用的事件侦听器函数 markyun.Event = { //页面加载完成后 readyEvent :function(fn) { if(fn==null) { fn=document; } v ...

  7. 一文帮你搞定90%的JS手写题

    还在害怕手写题吗,本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题.在工作中还可以对常用的需求进行手写实现,比如深拷贝.防抖节流等可以直接用于往后的项目中,提高项目开发效率.不说废话了,下 ...

  8. 2021年的几次面试让我死磕了17道JS手写题!

    1.浅拷贝.深拷贝的实现 浅拷贝 // 1. ...实现 let copy1 = {...{x:1}}// 2. Object.assign实现 let copy2 = Object.assign({ ...

  9. 【面试】970- 一文帮你搞定90%的JS手写题

    还在害怕手写题吗,本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题.在工作中还可以对常用的需求进行手写实现,比如深拷贝.防抖节流等可以直接用于往后的项目中,提高项目开发效率.不说废话了,下 ...

最新文章

  1. 7、计算机图形学——图形管线渲染与纹理映射
  2. 子域名/目录暴力工具Gobuster
  3. flex swf和movieclip之前的微妙关系
  4. java 使用webmagic 爬虫框架爬取博客园数据
  5. TP框架表单验证 【包含ajax方法】
  6. 不可重入锁和可重入锁
  7. oracle全局批准供应商,Oracle EBS-SQL (PO-7):检查异常-非批准的供应商设置供货比例.sql...
  8. Perl 6 语言的糟粕
  9. Python_类的特殊成员方法
  10. 跟着图灵去听课——海底捞敏捷之道纪要
  11. 一个好用的在线java反编译工具
  12. ubuntu 下安装ibus 中文输入法
  13. spring过滤器、拦截器
  14. 浅谈 Java 24个设计模式(23个GoF设计模式 + 简单工厂模式) 之 六个创建型模式...
  15. 002 splitter
  16. 云呐|PDA无线固定资产盘点管理系统
  17. paper:DeepAR: Probabilistic forecasting with autoregressive recurrent networks DeepAR模型
  18. 计算机查询网络连接,本地网络查询方法大全
  19. 从50分到90分,网站性能优化实践
  20. Ceph RBD API librdb 读流程源码分析

热门文章

  1. 从人工智能到物联网……这些公司如何改变农业与食品工业
  2. kepserver在设备上添加项目失败_隔空投送存储项目失败怎么办
  3. 开发工具 - WakaTime 时间记录
  4. linux版本的多屏协同,一招搞定手机和电脑的多屏协同
  5. 弹性裸金属服务器EBM
  6. charles对iOS手机的https进行抓包(图文教程)
  7. 对苹果maccms网站漏洞进行修复解决过程
  8. 阿里云短信平台实现手机验证码登录
  9. b3dm ~ ( Batched 3D Model )
  10. win10下git命令窗口快速命令