原文链接:Jack Pu's Blog

虽说我们很多时候前端很少有机会接触到算法。实际上学习数据结构与算法对于工程师去理解和分析问题都是有帮助的。如果将来当我们面对较为复杂的问题,这些基础知识的积累可以帮助我们更好的优化解决思路。

Q1 判断一个单词是否是回文?

回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。比如 mamam redivider .

很多人拿到这样的题目非常容易想到用for 将字符串颠倒字母顺序然后匹配就行了。其实重要的考察的就是对于reverse的实现。其实我们可以利用现成的函数,将字符串转换成数组,这个思路很重要,我们可以拥有更多的自由度去进行字符串的一些操作。

  1. function checkPalindrom(str) {
  2. return str == str.split('').reverse().join('');
  3. }

Q2 去掉一组整型数组重复的值

比如 输入: [1,13,24,11,11,14,1,2],  输出: [1,13,24,11,14,2] ,需要去掉重复的11 和 1 这两个元素。

主要考察个人对Object的使用,利用key来进行筛选。

  1. **
  2. * unique an array
  3. **/
  4. let unique = function(arr) {
  5. let hashTable = {};
  6. let data = [];
  7. for(let i=0,l=arr.length;i<l;i++) {
  8. if(!hashTable[arr[i]]) {
  9. hashTable[arr[i]] = true;
  10. data.push(arr[i]);
  11. }
  12. }
  13. return data
  14.  
  15. }
  16.  
  17. module.exports = unique;

Q3 统计一个字符串出现最多的字母

给出一段英文连续的英文字符窜,找出重复出现次数最多的字母

比如: 输入:afjghdfraaaasdenas  输出 : a

前面出现过去重的算法,这里需要是统计重复次数。

  1. function findMaxDuplicateChar(str) {
  2. if(str.length == 1) {
  3. return str;
  4. }
  5. let charObj = {};
  6. for(let i=0;i<str.length;i++) {
  7. if(!charObj[str.charAt(i)]) {
  8. charObj[str.charAt(i)] = 1;
  9. }else{
  10. charObj[str.charAt(i)] += 1;
  11. }
  12. }
  13. let maxChar = '',
  14. maxValue = 1;
  15. for(var k in charObj) {
  16. if(charObj[k] >= maxValue) {
  17. maxChar = k;
  18. maxValue = charObj[k];
  19. }
  20. }
  21. return maxChar;
  22.  
  23. }
  24.  
  25. module.exports = findMaxDuplicateChar;

Q4 排序算法

如果说到算法题目的话,应该大多都是比较开放的题目,不限定算法的实现,但是一定要求掌握其中的几种,所以冒泡排序,这种较为基础并且便于理解记忆的算法一定需要熟记于心。冒泡排序算法就是依次比较大小,小的的大的进行位置上的交换。

  1. function bubbleSort(arr) {
  2. for(let i = 0,l=arr.length;i<l-1;i++) {
  3. for(let j = i+1;j<l;j++) {
  4. if(arr[i]>arr[j]) {
  5. let tem = arr[i];
  6. arr[i] = arr[j];
  7. arr[j] = tem;
  8. }
  9. }
  10. }
  11. return arr;
  12. }
  13. module.exports = bubbleSort;

  除了冒泡排序外,其实还有很多诸如 插入排序快速排序希尔排序 等。每一种排序算法都有各自的特点。全部掌握也不需要,但是心底一定要熟悉几种算法。 比如快速排序,其效率很高,而其基本原理如图(来自wiki):

算法参考某个元素值,将小于它的值,放到左数组中,大于它的值的元素就放到右数组中,然后递归进行上一次左右数组的操作,返回合并的数组就是已经排好顺序的数组了。

  1. function quickSort(arr) {
  2.  
  3. if(arr.length<=1) {
  4. return arr;
  5. }
  6.  
  7. let leftArr = [];
  8. let rightArr = [];
  9. let q = arr[0];
  10. for(let i = 1,l=arr.length; i<l; i++) {
  11. if(arr[i]>q) {
  12. rightArr.push(arr[i]);
  13. }else{
  14. leftArr.push(arr[i]);
  15. }
  16. }
  17.  
  18. return [].concat(quickSort(leftArr),[q],quickSort(rightArr));
  19. }
  20.  
  21. module.exports = quickSort;

学习地址,通过动画演示算法的实现。

HTML5 Canvas Demo: Sorting Algorithms

Q5 不借助临时变量,进行两个整数的交换

  举例:输入 a = 2, b = 4 输出 a = 4, b =2

  这种问题非常巧妙,需要大家跳出惯有的思维,利用 a , b进行置换。

  主要是利用 + - 去进行运算,类似 a = a + ( b - a) 实际上等同于最后 的 a = b;

  1. function swap(a , b) {
  2. b = b - a;
  3. a = a + b;
  4. b = a - b;
  5. return [a,b];
  6. }
  7.  
  8. module.exports = swap;

Q6 使用canvas 绘制一个有限度的斐波那契数列的曲线?

数列长度限定在9.

斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列主要考察递归的调用。我们一般都知道定义

  1. fibo[i] = fibo[i-1]+fibo[i-2];

生成斐波那契数组的方法

  1. function getFibonacci(n) {
  2. var fibarr = [];
  3. var i = 0;
  4. while(i<n) {
  5. if(i<=1) {
  6. fibarr.push(i);
  7. }else{
  8. fibarr.push(fibarr[i-1] + fibarr[i-2])
  9. }
  10. i++;
  11. }
  12.  
  13. return fibarr;
  14. }

剩余的工作就是利用canvas arc方法进行曲线绘制了

DEMO参考

Q7 找出下列正数组的最大差值

比如: 输入 [10,5,11,7,8,9]  输出 6

这是通过一道题目去测试对于基本的数组的最大值的查找,很明显我们知道,最大差值肯定是一个数组中最大值与最小值的差。

  1. function getMaxProfit(arr) {
  2.  
  3. var minPrice = arr[0];
  4. var maxProfit = 0;
  5.  
  6. for (var i = 0; i < arr.length; i++) {
  7. var currentPrice = arr[i];
  8.  
  9. minPrice = Math.min(minPrice, currentPrice);
  10.  
  11. var potentialProfit = currentPrice - minPrice;
  12.  
  13. maxProfit = Math.max(maxProfit, potentialProfit);
  14. }
  15.  
  16. return maxProfit;
  17. }

Q8 随机生成指定长度的字符串

实现一个算法,随机生成指制定长度的字符窜。

比如:给定 长度 8 输出 4ldkfg9j

  1. function randomString(n) {
  2. let str = 'abcdefghijklmnopqrstuvwxyz9876543210';
  3. let tmp = '',
  4. i = 0,
  5. l = str.length;
  6. for (i = 0; i < n; i++) {
  7. tmp += str.charAt(Math.floor(Math.random() * l));
  8. }
  9. return tmp;
  10. }
  11.  
  12. module.exports = randomString;

Q9 实现类似getElementsByClassName 的功能

  自己实现一个函数,查找某个DOM节点下面的包含某个class的所有DOM节点?不允许使用原生提供的 getElementsByClassName querySelectorAll 等原生提供DOM查找函数。

  1. function queryClassName(node, name) {
  2. var starts = '(^|[ \n\r\t\f])',
  3. ends = '([ \n\r\t\f]|$)';
  4. var array = [],
  5. regex = new RegExp(starts + name + ends),
  6. elements = node.getElementsByTagName("*"),
  7. length = elements.length,
  8. i = 0,
  9. element;
  10.  
  11. while (i < length) {
  12. element = elements[i];
  13. if (regex.test(element.className)) {
  14. array.push(element);
  15. }
  16.  
  17. i += 1;
  18. }
  19.  
  20. return array;
  21. }

Q10 使用JS 实现二叉查找树(Binary Search Tree)

一般叫全部写完的概率比较少,但是重点考察你对它的理解和一些基本特点的实现。 二叉查找树,也称二叉搜索树、有序二叉树(英语:ordered binary tree)是指一棵空树或者具有下列性质的二叉树:

  • 任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 任意节点的左、右子树也分别为二叉查找树;
  • 没有键值相等的节点。二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。为O(log n)。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。

在写的时候需要足够理解二叉搜素树的特点,需要先设定好每个节点的数据结构

  1. class Node {
  2. constructor(data, left, right) {
  3. this.data = data;
  4. this.left = left;
  5. this.right = right;
  6. }
  7. }

树是有节点构成,由根节点逐渐延生到各个子节点,因此它具备基本的结构就是具备一个根节点,具备添加,查找和删除节点的方法.

  1. class BinarySearchTree {
  2.  
  3. constructor() {
  4. this.root = null;
  5. }
  6.  
  7. insert(data) {
  8. let n = new Node(data, null, null);
  9. if (!this.root) {
  10. return this.root = n;
  11. }
  12. let currentNode = this.root;
  13. let parent = null;
  14. while (1) {
  15. parent = currentNode;
  16. if (data < currentNode.data) {
  17. currentNode = currentNode.left;
  18. if (currentNode === null) {
  19. parent.left = n;
  20. break;
  21. }
  22. } else {
  23. currentNode = currentNode.right;
  24. if (currentNode === null) {
  25. parent.right = n;
  26. break;
  27. }
  28. }
  29. }
  30. }
  31.  
  32. remove(data) {
  33. this.root = this.removeNode(this.root, data)
  34. }
  35.  
  36. removeNode(node, data) {
  37. if (node == null) {
  38. return null;
  39. }
  40.  
  41. if (data == node.data) {
  42. // no children node
  43. if (node.left == null && node.right == null) {
  44. return null;
  45. }
  46. if (node.left == null) {
  47. return node.right;
  48. }
  49. if (node.right == null) {
  50. return node.left;
  51. }
  52.  
  53. let getSmallest = function(node) {
  54. if(node.left === null && node.right == null) {
  55. return node;
  56. }
  57. if(node.left != null) {
  58. return node.left;
  59. }
  60. if(node.right !== null) {
  61. return getSmallest(node.right);
  62. }
  63.  
  64. }
  65. let temNode = getSmallest(node.right);
  66. node.data = temNode.data;
  67. node.right = this.removeNode(temNode.right,temNode.data);
  68. return node;
  69.  
  70. } else if (data < node.data) {
  71. node.left = this.removeNode(node.left,data);
  72. return node;
  73. } else {
  74. node.right = this.removeNode(node.right,data);
  75. return node;
  76. }
  77. }
  78.  
  79. find(data) {
  80. var current = this.root;
  81. while (current != null) {
  82. if (data == current.data) {
  83. break;
  84. }
  85. if (data < current.data) {
  86. current = current.left;
  87. } else {
  88. current = current.right
  89. }
  90. }
  91. return current.data;
  92. }
  93.  
  94. }
  95.  
  96. module.exports = BinarySearchTree;

完整代码 Github

JS常见的算法的更多相关文章

  1. JS常见排序算法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. js 常见数组算法

    数组方法概述 1.不改变原数组,返回新数组 concat() 连接两个或多个数组,两边的原始数组都不会变化,返回被连接数组的一个副本. join() 把数组中所有元素放入一个字符串中,返回字符串. s ...

  3. 常见排序算法(JS版)

    常见排序算法(JS版)包括: 内置排序,冒泡排序,选择排序,插入排序,希尔排序,快速排序(递归 & 堆栈),归并排序,堆排序,以及分析每种排序算法的执行时间. index.html <! ...

  4. 常见排序算法原理及JS代码实现

    目录 数组 sort() 方法 冒泡排序 选择排序 插入排序 希尔排序 归并排序 堆排序 快速排序 创建时间:2020-08-07 本文只是将作者学习的过程以及算法理解进行简单的分享,提供多一个角度的 ...

  5. JavaScript版几种常见排序算法

    今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...

  6. JS数据结构与算法——栈

    JS数据结构与算法--栈 1.栈结构概念 栈(Stack)是一种先进后出(LIFO Last in First out)的线性表,先进栈的将会比后进栈的先出栈. 栈的限制是仅允许在一端进行插入和删除运 ...

  7. js 实现各种算法 APP

    js 实现各种算法 APP 常见算法: 排序,搜索/查找,枚举,遍历,最短路径,二叉树 open source web app desktop app react native app flutter ...

  8. JS数据结构与算法-概述

    JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...

  9. 常见排序算法(附java代码)

    常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...

随机推荐

  1. Merkle Patricia Tree (MPT) 以太坊中的默克尔树

    本篇博文是自己学习mpt的过程,边学边记录,很多原理性内容非自己原创,好的博文将会以链接形式进行共享. 一.什么是mpt MPT是以太坊中的merkle改进树,基于基数树,即前缀树改进而来,大大提高了 ...

  2. RedHat/CentOS利用iso镜像做本地yum源

    在这里用iso或者光盘做本地yum源的方法是差不多的,只是用光盘的话Linux系统会自动挂载,用iso镜像的或需要手动挂载,这里就说挂载iso的方法吧. (1) 创建iso存放目录和挂载目录 mkdi ...

  3. 《剑指Offer》题十一~题二十

    十一.旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组{3, 4, 5, 1, 2}为{ ...

  4. 自测之Lesson10:管道

    题目:建立双向管道,实现:父进程向子进程传送一个字符串,子进程对该字符串进行处理(小写字母转为大写字母)后再传回父进程. 实现代码: #include <stdio.h> #include ...

  5. 软件工程 作业part1

    自我介绍 老师您好,我叫宋雨,本科在长春理工大学,专业是计算机科学与技术. 1.回想一下你曾经对计算机专业的畅想:当初你是如何做出选择计算机专业的决定?你认为过去接触的课程是否符合你对计算机专业的期待 ...

  6. Java之I/O流(第2部分)

    1. 节点类类型: 2. 访问文件: Demo_1: import java.io.FileInputStream; import java.io.FileNotFoundException; imp ...

  7. ajax 返回值问题

    错误示例:function returnFlag(){ $.ajax({ type:"post", dataType:"json", data:JSON.str ...

  8. 关于char, wchar_t, TCHAR, _T(),L,宏 _T、TEXT,_TEXT、L

    char :单字节变量类型,最多表示256个字符, wchar_t :宽字节变量类型,用于表示Unicode字符, 它实际定义在<string.h>里:typedef unsigned s ...

  9. linux路由表的配置

    linux路由表的配置 一.原理说明 1.路由表(table)从0到255进行编号,每个编号可以对应一个别名,编号和别名的对应关系在linux下放在/etc/iproute2/rt_tables这个文 ...

  10. Java 多线程序的一点理解

    synchronized 是java 内主要的同步标记 1 同步非静态方法 作用域范围只是当前对象在不同线程间的同步, 如果n 为Test外的对象,在不同的Test对象之间,等于没有同步, 该方法只能 ...