那些日常使用到的算法,也是面试经常问到的算法。
大家好,我是梦兽编程。
梦兽编程是非常讨厌八股文。但是出于无奈也没办法,市场就是这样。技术探讨本来是经验的分享,而在我国的情况变成了9年义务教育的死板“教科书”。
很多时候我们会被资本家压榨到无法思考,还那有空了解那些面试题的实际知识点?如果你刷到本片文章,那么所有的面试题背后的知识点将有梦兽编归纳总结放到那些被问烂的前端面试题栏目中进行更新迭代。从问题的出现与考点进行解答。
期待你的收藏我的个人网站。
日常开发中,我们多多少少需要使用一些算法技巧来完成我们的业务需求。那有哪些算法是我们是经常需要使用到呢?
既然是日常的技巧,也很有可能是面试高频的考题。
LRU
LRU 是 Least Recently Used 的缩写,即最近最少使用。LRU 缓存算法是一种缓存淘汰算法,它会选择最近最少使用的缓存数据进行淘汰。
简单来交就是使用的排在前面,不用的往后排或者删掉。类似历史记录一样。
LRU 缓存算法的思路是,缓存数据的访问频率越高,其被淘汰的可能性越小。因此,LRU 缓存算法会将最近被访问过的数据放在缓存的头部,而将最近最少被访问过的数据放在缓存的尾部。当缓存空间不足时,就淘汰缓存尾部的最少使用数据。
那这个我们需要怎么实现呢?
class LRUCache {
constructor(capacity) {
// LRU需要一个容器值
this.capacity = capacity;
this.map = new Map();
}
get(key) {
const value = this.map.get(key);
if (value === undefined) {
return -1
} else {
// 我们需要先将最近最少使用的键值对从缓存中逐出,然后再将新的键值对添加到缓存的开头。
this.map.delete(key);
this.map.set(key, value);
return value;
}
}
set(key, value) {
const haskey = this.map.has(key);
if (haskey) {
this.map.delete(key);
}
this.map.set(key, value);
if (this.map.size() > this.capacity) {
// 满的时候需要将他最后一位删除掉
this.map.delete(this.map.keys().next().value);
}
}
}
字流
当多次执行某一动作,每隔一段时间,只执行一次函数。
单位时间内只执行一次,这个是核心.如果你不知道这个是无法完成的.
function throttle(fn, waith) {
let lastTime = 0;
return (...arg) => {
const current = Date.now();
// 单位时间内才能执行
if (current - lastTime > waith) {
fn.apply(this, arg)
lastTime = current
}
}
}
如果你使用的是React,在React中存在重渲染问题.这个时候我们使用这种方式是不可取的.在react中可能需要需要额外的处理
import React, { useEffect } from 'react'
function useThrottle(fn, wait, desp) {
const { current } = React.useRef<{
timer: number | undefined
fn: Function
}>({
timer: undefined,
fn: () => { }
});
useEffect(() => {
current.fn = fn
}, [fn, desp])
return React.useCallback((...arg) => {
if (!current.timer) {
current.timer = setTimeout(() => {
delete current.timer
}, wait);
current.fn(...arg)
}
}, desp)
}
防抖
连续的事件,只需触发一次.
所以关键是需要清理一次setTimeout的管理,然后在setTimeout一次执行函数
function debounce(fn, wait) {
let timer;
return (...arg) => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn(...arg)
}, wait);
}
}
React Hooks版本
function useDebounce(fn, wait, desp) {
const { current } = useRef<{ timer: undefined | number, fn: Function }>({
timer: undefined,
fn: () => { }
})
useEffect(() => {
current.fn = fn
}, [fn])
return useCallback((...arg) => {
if (current.timer) {
clearTimeout(current.timer)
}
current.timer = setTimeout(() => {
current.fn(...arg)
}, wait);
}, desp)
}
快排
算法基础:快速排序是一种经典的排序算法,面试官希望考察面试者是否理解快速排序的思想和原理,并能够正确地实现快速排序算法。
编码能力:快速排序算法需要用代码实现,因此面试官希望考察面试者是否具备良好的编码能力,能够正确地编写快速排序算法的代码。
解决问题的能力:快速排序算法在最坏情况下的时间复杂度为 O(n^2),面试官希望考察面试者是否能够分析快速排序算法的复杂度,并能够提出优化方案。
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
const quickIndex = Math.floor(arr.length / 2); // 取中间值
const quick = arr.splice(quickIndex, 1)[0];
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < quick) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([quick], quickSort(right));
}
const arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
console.log(quickSort(arr)); // [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
冒泡排序
冒泡排序是一种简单的排序算法,其基本思想是:在序列中,相邻的元素两两比较,如果前面的元素大于后面的元素,则交换它们的位置。重复该过程,直到序列中没有元素需要交换为止。
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j + 1], arr[j]] = [arr[j], arr[j + 1]];
}
}
}
return arr
}
插入排序
function insertionSort(arr) {
let len = arr.length;
for (let i = 1; i < len; i++) {
const current = arr[i];
let j = i - 1;
while (j >= 0 && arr[j] > current) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = current;
}
return arr
}
递归
这道题一般都会出类似将某些嵌套关系的数据结构进行展平的操作。
例如
const a = { a: 1, b: 2, c: { d: 3, h: { e: 4 } } }
output:
{a: 1, b: 2, d: 3, e: 4}
记得你return是 result ,在值为object需要进行合并就好了。
function flat(object) {
let result = {};
for (let key in object) {
if (typeof object[key] === 'object') {
Object.assign(result, flat(object[key]))
}else{
Object.assign(result, { [key]: object[key] })
}
}
return result;
}
查询是否存在单一字节
abcabcd
output:
d
function repeat(str) {
let map = new Map();
for (let i = 0; i < str.length; i++) {
const values = map.get(str[i]);
if (values === undefined) {
map.set(str[i], 1);
} else {
map.set(str[i], values + 1);
}
}
const result = [];
for (const [key, value] of map) {
if (value === 1) {
result.push(key)
}
}
return result.length > 0 ? result : null;
}
手写柯里化
// 实现一个add方法, 使计算结果能够满足以下预期
add(1)(2)(3) = 6
add(1,2,3)(4) = 10
add(1)(2)(3)(4)(5) = 15
function add() {
// 定义一个数组进行参数的存储
var _args = Array.prototype.slice.call(arguments)
// 存储所有参数
var _adder = function() {
_args.push(...arguments)
return _adder
}
// 利用toString的隐式转换的特性,进行结果计算并返回
_adder.toString = function() {
return _args.reduce((a, b) => a + b)
}
return _adder
}
React Hooks
编写一个自定义hook,接受一个默认值,返回一个当前值和setstate的方法。该hook将使用1ocalStorage机制将输入的值存储在浏览器中, 并在下一次访问时优先使用该值(若没有则使用defaultValue)
function useLocalState(defaultValue, key) {
const [value, setValue] = useState(localStorage.getItem(key) || defaultValue)
const setLocalState = (newValue) => {
setValue(newValue)
localStorage.setItem(key, newValue)
}
return [value, setLocalState]
}
请求Hooks
function useRequest(url) {
const [data, setData] = useState()
const [error, setError] = useState()
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => setData(data))
.catch(error => setError(error))
}, [])
return [data, error]
}
本文使用 markdown.com.cn 排版
转载自:https://juejin.cn/post/7296753988815814691