前端JS面试中常见的算法问题总结


Posted in Javascript onDecember 23, 2016

前言

学习数据结构与算法对于工程师去理解和分析问题都是有帮助的。如果将来当我们面对较为复杂的问题,这些基础知识的积累可以帮助我们更好的优化解决思路。下面罗列在前端面试中经常撞见的几个问题吧。

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

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

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

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

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

比如输入: [1,13,24,11,11,14,1,2]

输出: [1,13,24,11,14,2]

需要去掉重复的11 和 1 这两个元素。

这道问题出现在诸多的前端面试题中,主要考察个人对Object的使用,利用key来进行筛选。

/**
* unique an array 
**/
let unique = function(arr) { 
 let hashTable = {};
 let data = [];
 for(let i=0,l=arr.length;i<l;i++) {
  if(!hashTable[arr[i]]) {
   hashTable[arr[i]] = true;
   data.push(arr[i]);
  }
 }
 return data

}

module.exports = unique;

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

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

输入 : afjghdfraaaasdenas

输出 : a

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

function findMaxDuplicateChar(str) { 
 if(str.length == 1) {
  return str;
 }
 let charObj = {};
 for(let i=0;i<str.length;i++) {
  if(!charObj[str.charAt(i)]) {
   charObj[str.charAt(i)] = 1;
  }else{
   charObj[str.charAt(i)] += 1;
  }
 }
 let maxChar = '',
   maxValue = 1;
 for(var k in charObj) {
  if(charObj[k] >= maxValue) {
   maxChar = k;
   maxValue = charObj[k];
  }
 }
 return maxChar;

}

module.exports = findMaxDuplicateChar;

Q4 排序算法

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

function bubbleSort(arr) { 
  for(let i = 0,l=arr.length;i<l-1;i++) {
    for(let j = i+1;j<l;j++) { 
     if(arr[i]>arr[j]) {
        let tem = arr[i];
        arr[i] = arr[j];
        arr[j] = tem;
      }
    }
  }
  return arr;
}
module.exports = bubbleSort;

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

前端JS面试中常见的算法问题总结

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

function quickSort(arr) {

  if(arr.length<=1) {
    return arr;
  }

  let leftArr = [];
  let rightArr = [];
  let q = arr[0];
  for(let i = 1,l=arr.length; i<l; i++) {
    if(arr[i]>q) {
      rightArr.push(arr[i]);
    }else{
      leftArr.push(arr[i]);
    }
  }

  return [].concat(quickSort(leftArr),[q],quickSort(rightArr));
}

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;

function swap(a , b) { 
 b = b - a;
 a = a + b;
 b = a - b;
 return [a,b];
}

module.exports = swap;

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

前端JS面试中常见的算法问题总结 

数列长度限定在9.

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

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

生成斐波那契数组的方法

function getFibonacci(n) { 
 var fibarr = [];
 var i = 0;
 while(i<n) {
  if(i<=1) {
   fibarr.push(i);
  }else{
   fibarr.push(fibarr[i-1] + fibarr[i-2])
  }
  i++;
 }

 return fibarr;
}

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

DEMO

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

输入 [10,5,11,7,8,9]

输出 6

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

function getMaxProfit(arr) {

  var minPrice = arr[0];
  var maxProfit = 0;

  for (var i = 0; i < arr.length; i++) {
    var currentPrice = arr[i];

    minPrice = Math.min(minPrice, currentPrice);

    var potentialProfit = currentPrice - minPrice;

    maxProfit = Math.max(maxProfit, potentialProfit);
  }

  return maxProfit;
}

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

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

比如给定 长度 8  输出 4ldkfg9j

function randomString(n) { 
 let str = 'abcdefghijklmnopqrstuvwxyz9876543210';
 let tmp = '',
   i = 0,
   l = str.length;
 for (i = 0; i < n; i++) {
  tmp += str.charAt(Math.floor(Math.random() * l));
 }
 return tmp;
}

module.exports = randomString;

Q9 实现类似getElementsByClassName 的功能

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

function queryClassName(node, name) { 
 var starts = '(^|[ \n\r\t\f])',
    ends = '([ \n\r\t\f]|$)';
 var array = [],
    regex = new RegExp(starts + name + ends),
    elements = node.getElementsByTagName("*"),
    length = elements.length,
    i = 0,
    element;

  while (i < length) {
    element = elements[i];
    if (regex.test(element.className)) {
      array.push(element);
    }

    i += 1;
  }

  return array;
}

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

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

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

前端JS面试中常见的算法问题总结

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

class Node { 
 constructor(data, left, right) {
  this.data = data;
  this.left = left;
  this.right = right;
 }

}

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

class BinarySearchTree {

 constructor() {
  this.root = null;
 }

 insert(data) {
  let n = new Node(data, null, null);
  if (!this.root) {
   return this.root = n;
  }
  let currentNode = this.root;
  let parent = null;
  while (1) {
   parent = currentNode;
   if (data < currentNode.data) {
    currentNode = currentNode.left;
    if (currentNode === null) {
     parent.left = n;
     break;
    }
   } else {
    currentNode = currentNode.right;
    if (currentNode === null) {
     parent.right = n;
     break;
    }
   }
  }
 }

 remove(data) {
  this.root = this.removeNode(this.root, data)
 }

 removeNode(node, data) {
  if (node == null) {
   return null;
  }

  if (data == node.data) {
   // no children node
   if (node.left == null && node.right == null) {
    return null;
   }
   if (node.left == null) {
    return node.right;
   }
   if (node.right == null) {
    return node.left;
   }

   let getSmallest = function(node) {
    if(node.left === null && node.right == null) {
     return node;
    }
    if(node.left != null) {
     return node.left;
    }
    if(node.right !== null) {
     return getSmallest(node.right);
    }

   }
   let temNode = getSmallest(node.right);
   node.data = temNode.data;
   node.right = this.removeNode(temNode.right,temNode.data);
   return node;

  } else if (data < node.data) {
   node.left = this.removeNode(node.left,data);
   return node;
  } else {
   node.right = this.removeNode(node.right,data);
   return node;
  }
 }

 find(data) {
  var current = this.root;
  while (current != null) {
   if (data == current.data) {
    break;
   }
   if (data < current.data) {
    current = current.left;
   } else {
    current = current.right
   }
  }
  return current.data;
 }

}

module.exports = BinarySearchTree;

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
jquery实现图片等比例缩放以及max-width在ie中不兼容解决
Mar 21 Javascript
JQuery的Ajax跨域请求原理概述及实例
Apr 26 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
May 08 Javascript
JavaScript作用域链示例分享
May 27 Javascript
详解JavaScript中shift()方法的使用
Jun 09 Javascript
给before和after伪元素设置js效果的方法
Dec 04 Javascript
AngularJS入门教程之Scope(作用域)
Jul 27 Javascript
node.js版本管理工具n无效的原理和解决方法
Nov 24 Javascript
Vue动态组件实例解析
Aug 20 Javascript
自定义vue组件发布到npm的方法
May 09 Javascript
vue中利用iscroll.js解决pc端滚动问题
Feb 15 Javascript
Vue通过阿里云oss的url连接直接下载文件并修改文件名的方法
Dec 25 Vue.js
Bootstrap源码解读导航条(7)
Dec 23 #Javascript
livereload工具实现前端可视化开发【推荐】
Dec 23 #Javascript
浅谈jQuery操作类数组的工具方法
Dec 23 #Javascript
jquery pagination插件动态分页实例(Bootstrap分页)
Dec 23 #Javascript
详解jQuery中的DOM操作
Dec 23 #Javascript
Bootstrap table两种分页示例
Dec 23 #Javascript
理解AngularJs篇:30分钟快速掌握AngularJs
Dec 23 #Javascript
You might like
php Mysql日期和时间函数集合
2007/11/16 PHP
PHP连接SQLServer2005 的问题解决方法
2010/07/19 PHP
使用PHP curl模拟浏览器抓取网站信息
2013/10/28 PHP
PHP中单例模式与工厂模式详解
2017/02/17 PHP
yii2项目实战之restful api授权验证详解
2017/05/20 PHP
PHP内存溢出优化代码详解
2021/02/26 PHP
Javascript YUI 读码日记之 YAHOO.util.Dom - Part.3
2008/03/22 Javascript
For循环中分号隔开的3部分的执行顺序探讨
2014/05/27 Javascript
jQuery移动web开发之页面跳转和加载外部页面的实现
2015/12/04 Javascript
CascadeView级联组件实现思路详解(分离思想和单链表)
2016/04/12 Javascript
JS制作图形验证码实现代码
2020/10/19 Javascript
Angular的模块化(代码分享)
2016/12/26 Javascript
Javascript实现购物车功能的详细代码
2018/05/08 Javascript
详解vue中移动端自适应方案
2019/05/05 Javascript
vue实现手机号码的校验实例代码(防抖函数的应用场景)
2019/09/05 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
Vant 在vue-cli 4.x中按需加载操作
2020/11/05 Javascript
[02:01]2018完美盛典-开场舞《双子星》
2018/12/16 DOTA
[02:55]含熏伴清风,风行者至宝、屠夫身心及典藏宝瓶二展示
2020/09/08 DOTA
python学习笔记:字典的使用示例详解
2014/06/13 Python
详解pandas安装若干异常及解决方案总结
2019/01/10 Python
python买卖股票的最佳时机(基于贪心/蛮力算法)
2019/07/05 Python
Django中ajax发送post请求 报403错误CSRF验证失败解决方案
2019/08/13 Python
Python lambda表达式filter、map、reduce函数用法解析
2019/09/11 Python
简单介绍django提供的加密算法
2019/12/18 Python
Spring http服务远程调用实现过程解析
2020/06/11 Python
python 如何快速复制序列
2020/09/07 Python
使用css3背景渐变中的透明度来设置不同颜色的背景渐变
2014/03/31 HTML / CSS
思想品德自我评价
2014/02/04 职场文书
安全生产网格化管理实施方案
2014/03/01 职场文书
《月光启蒙》教学反思
2014/03/01 职场文书
社区节水倡议书
2015/04/29 职场文书
《坐井观天》教学反思
2016/02/18 职场文书
应届毕业生的自我评价
2019/06/21 职场文书
使用redis生成唯一编号及原理示例详解
2021/09/15 Redis