前端工程师面试指南——算法篇
CruxF opened this issue · comments
判断一个单词是否是回文字符
概念: 回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。比如 mamam、redivider等。
很多人拿到这样的题目非常容易想到用for 将字符串颠倒字母顺序然后匹配就行了。其实重要的考察的就是对于reverse的实现。其实我们可以利用现成的函数,将字符串转换成数组,这个思路很重要,我们可以拥有更多的自由度去进行字符串的一些操作。
function checkPalindrom(str) {
if(str == str.split('').reverse().join('')) {
console.log("true")
}
}
checkPalindrom("mamam")
去掉一组整型数组重复的值
这道问题出现在诸多的前端面试题中,主要考察个人对Object的使用,利用key来进行筛选。
function unique(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]);
}
}
console.log(data);
}
let arrs = [4, 5, 2, 4, 1];
unique(arrs);
统计一个字符串出现最多的字母
function findMaxDuplicateChar(str) {
if (str.length <= 1) {
return str;
}
let charObj = {};
for (let i = 0; i < str.length; i++) {
// charAt() 方法可返回指定位置的字符。
// console.log(str.charAt(i))
if (!charObj[str.charAt(i)]) {
charObj[str.charAt(i)] = 1;
} else {
charObj[str.charAt(i)] += 1;
}
}
// {r:1,e:1,q:1,a:3,d:1,f:1}
// console.log(charObj)
let maxChar = "";
let maxValue = 1;
for (var k in charObj) {
if (charObj[k] >= maxValue) {
maxChar = k;
maxValue = charObj[k];
}
}
console.log(maxChar);
}
findMaxDuplicateChar("reqaaadf");
排序算法
如果抽到算法题目的话,应该大多都是比较开放的题目,不限定算法的实现,但是一定要求掌握其中的几种,所以冒泡排序,这种较为基础并且便于理解记忆的算法一定需要熟记于心。冒泡排序算法就是依次比较大小,小的跟大的进行位置上的交换。
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;
}
}
}
console.log(arr);
}
let arrs = [3, 55, 12];
bubbleSort(arrs);
// 推理过程
当i=0
j ==> 1
arr[i] ==> 3
arr[j] ==> 55
也就是arr[0] = 0,arr[1] = 55
当i=1
j ==> 2
arr[i] ==> 55
arr[j] ==> 12
tem ==> arr[i]=55
arr[i] = arr[j] = 12
arr[j] = 55
也就是arr[1] = 12,arr[2] = 55
除了冒泡排序外,其实还有很多诸如 插入排序,快速排序,希尔排序等。每一种排序算法都有各自的特点。全部掌握也不需要,但是心底一定要熟悉几种算法。
比如快速排序,其效率很高,算法参考某个元素值,将小于它的值,放到左数组中,大于它的值的元素就放到右数组中,然后递归进行上一次左右数组的操作,返回合并的数组就是已经排好顺序的数组了。
function quickSort(arr) {
//如果数组<=1,则直接返回
if (arr.length <= 1) {
return arr;
}
var pivotIndex = Math.floor(arr.length / 2);
//找基准,并把基准从原数组删除
var pivot = arr.splice(pivotIndex, 1)[0];
//定义左右数组
var left = [];
var right = [];
//比基准小的放在left,比基准大的放在right
for (var i = 0; i < arr.length; i++) {
if (arr[i] <= pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
//递归
return quickSort(left).concat([pivot], quickSort(right));
}
console.log(quickSort([4, 2, 6, 7, 1]));
下面是比较复杂难懂但是时间复杂度较低的代码,参考文章
// 原地交换函数,而非用临时数组
function swap(array, a, b) {
[array[a], array[b]] = [array[b], array[a]];
}
// 划分操作函数
function partition(array, left, right) {
// 用index取中间值而非splice
const pivot = array[Math.floor((right + left) / 2)];
let i = left;
let j = right;
while (i <= j) {
while (compare(array[i], pivot) === -1) {
i++;
}
while (compare(array[j], pivot) === 1) {
j--;
}
if (i <= j) {
swap(array, i, j);
i++;
j--;
}
}
return i;
}
// 比较函数
function compare(a, b) {
if (a === b) {
return 0;
}
return a < b ? -1 : 1;
}
function quick(array, left, right) {
let index;
// 第一次:[3,2,1] 0 2
// 第二次:[1,2,3] 0 1
// console.log(array,left,right)
if (array.length > 1) {
index = partition(array, left, right);
// 第一次:2
// 第二次:1
// console.log(index)
if (left < index - 1) {
quick(array, left, index - 1);
}
if (index < right) {
quick(array, index, right);
}
}
// return array;
console.log(array);
}
function quickSort(array) {
return quick(array, 0, array.length - 1);
};
let arrs = [3, 2, 1]
quickSort(arrs);
不借助临时变量,进行两个整数的交换
这种问题非常巧妙,需要大家跳出惯有的思维,利用 a , b进行置换。主要是利用 + – 去进行运算,类似 a = a + ( b – a) 实际上等同于最后 的 a = b;
function swap(a, b) {
b = b - a;
a = a + b;
b = a - b;
return [a, b];
}
console.log(swap(3, 8));
写一个斐波那契数列,长度限定为9
斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列主要考察递归的调用。
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;
}
console.log(getFibonacci(9))
找出正数组的最大差值
这是通过一道题目去测试对于基本的数组的最大值的查找,很明显我们知道,最大差值肯定是一个数组中最大值与最小值的差。
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;
}
// 出现bug
console.log(getMaxProfit([65, 6, 2]));
// 出现bug
console.log(getMaxProfit([65, 6]));
// 正常
console.log(getMaxProfit([65, 6, 99]));
下面是一个暂时没有bug的实现方式
function getMaxProfit(arr) {
var max = arr[0];
var min = arr[0];
var res = 0;
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i]
}
res = max - min;
}
return res;
}
console.log(getMaxProfit([65, 6, 2]))
console.log(getMaxProfit([65, 6]))
console.log(getMaxProfit([65, 6, 99]))
随机生成指定长度的字符串
function randomString(n) {
let str = 'abcdefghijklmnopqrstuvwxyz9876543210';
let tmp = '';
let i = 0;
let l = str.length;
for (i = 0; i < n; i++) {
tmp += str.charAt(Math.floor(Math.random() * l));
}
return tmp;
}
console.log(randomString(5))