1、实现一个方法,可以从一个对象中批量获取属性
const obj = { selector: { to1: { toutiao: "FE Coder" } }, target: [1, 2, { name: 'byted' }, [3,4]] }
console.log(getValueByStr(obj, `target[2][${'name'}]`, `selector[${'to' + 1}].toutiao`))
// 输出[ 'byted', 'FE Coder' ]
function getValueBykey(data, pathStr) {
const pathList = pathStr.split('.')
return pathList.reduce((p, n) => {
if (/\[\w+\]/.test(n)) {
const keyList = splitMatchKey(n)
return keyList.reduce((pre, next) => {
return pre[next]
}, p)
}
return p[n]
}, data)
}
function splitMatchKey(str) {
return str.split(/\[(\w+)\]/).filter(item => item)
}
function getValueByStr(data, ...args) {
return args.reduce((pre, next) => {
pre.push(getValueBykey(data, next))
return pre
}, [])
}
2、实现add函数var ans = add(1)(2)(3)(4)...,console.log(ans)//输出1+2+3+4+...之和
function add(a) {
var temp = function (b) { return add(a + b) }
temp.valueOf = temp.toString = function () { return a }
return temp
}
3、01背包问题
/**背包总体积:8
* [2, 3, 4, 5] weigth // 体积
* [3, 4, 5, 6] worth // 价值
*/
动态规划解法
const weightList = [2, 3, 4, 5, 6, 7, 8, 9, 10] // 物品所占体积
const worthList = [3, 4, 5, 6, 7, 8, 9, 10, 11]
let maxWorthArray = new Array(9).fill(new Array(9))
function getMaxWorth(weightSum, skuIndex) {
let maxWorth = 0
if (maxWorthArray[weightSum] && maxWorthArray[weightSum][skuIndex]) {
maxWorth = maxWorthArray[weightSum][skuIndex]
} else if (skuIndex == 0) {
if (weightSum >= weightList[skuIndex]) {
maxWorth = worthList[skuIndex]
} else {
maxWorth = 0
}
} else if (weightSum >= weightList[skuIndex]) {
maxWorth = Math.max(getMaxWorth(weightSum - weightList[skuIndex], skuIndex - 1) + worthList[skuIndex], getMaxWorth(weightSum, skuIndex - 1))
} else {
maxWorth = getMaxWorth(weightSum, skuIndex - 1)
maxWorthArray[weightSum][skuIndex] = maxWorth
}
return maxWorth
}
贪心算法
function greed(values, weights, capacity) {
let len = values.length
const ratioList = values.reduce((pre, next, index) => {
pre.push({
worth: next,
weight: weights[index],
ratio: (next/weights[index]).toFixed(1)
})
return pre
}, [])
ratioList.sort((a, b) => {
return b.ratio - a.ratio
})
console.log(ratioList)
let maxWorth = 0
let remainRoom = capacity
for (let i = 0; i < len; i++) {
if (remainRoom > 0 && ratioList[i].weight <= remainRoom) {
// let num = Math.floor(remainRoom / ratioList[i].weight)
maxWorth += ratioList[i].worth
remainRoom -= ratioList[i].weight
} else {
break
}
}
return maxWorth
}
4、给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 num1 成为一个有序数组 const nums1 = [8,9,10] const nums2 = [4, 5, 6]
function groupArray(array1, m, array2, n) {
let len1 = m - 1
let len2 = n - 1
let len = m + n - 1
while (len2 > -1) {
if (len1 < 0 && len > 0) {
array1[len--] = array2[len2--]
}
array1[len--] = array1[len1] > array2[len2] ? array1[len1 --] : array2[len2 --]
}
return array1
}
5、在一个数组中找出三数之和为target值,给定 nums = [2, 7, 9, 11, 15, 16], target = 28
function getSumNumber(array, target) {
if (array.length <= 3) return array
for (let index = 0; index < array.length - 2; index++) {
let left = index + 1
let right = array.length - 1
while (left < right) {
const sum = array[left] + array[right] + array[index]
if (sum > target) {
right --
} else if(sum < target) {
left ++
} else {
return [array[index], array[left], array[right]]
}
}
}
}
6、求最长无重复子串
function getMaxNoRepeatStr(str) {
let left = 0
let len = str.length
let temp = {}
let max = 0
let maxStr = ''
for (let i = 0; i < len; i++) {
if (temp.hasOwnProperty(str[i])) {
left = Math.max(temp[str[i]] + 1, left)
}
max = Math.max(max, i - left + 1)
if (max > maxStr.length) {
maxStr = str.substr(left, max)
}
temp[str[i]] = i
}
console.log(maxStr)
return max
}
7、给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效
function compare(str) {
const leftToRight = {
'(': ')',
'{': '}',
'[': ']'
}
const rightToLeft = {
')': '(',
'}': '{',
']': '['
}
let stack = []
for (let key of str) {
if (leftToRight[key]) { // 如果是左括号直接插入
stack.push(key)
} else {
const tail = stack.slice(-1).toString()
if (rightToLeft[key] && rightToLeft[key] === tail) {
stack.pop()
} else {
return false
}
}
}
return !stack.length
}
8、给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
function getBetween(n, k) {
if (n < k) {
return []
}
let res = []
function helper(index = 1, i, prev = []) {
if ((prev.length + i) < k) {
return
}
while (i) {
if (index === k) {
res.push([...prev, i])
} else {
helper(index + 1, i-1, [...prev, i])
}
i--
}
}
helper(1, n)
return res
}
9、堆排序算法
function maxHeapify(arr, i, size) {
let left, right, minlr = -1
while (i < size) {
left = 2*i
right = left + 1
if (left > size) {
break
}
if (left <= size && right > size) { // 只有左节点
minlr = left
}
if (left <= size && right <= size) { // 左右节点都有
minlr = arr[left] > arr[right] ? right : left
}
if (arr[i] > arr[minlr]) {
swap(arr, minlr, i)
i = minlr
} else {
break
}
}
}
function swap(arr, i, j) {
let temp = arr[j]
arr[j] = arr[i]
arr[i] = temp
}
function buildMaxHeap(arr) { // 构建小顶堆
if (!Array.isArray(arr)) return []
//将null插到数组第一个位置上
arr.unshift(null)
let lastParentIndex = Math.floor((arr.length - 1) / 2)
for (let i = lastParentIndex; i > 0; i--) {
maxHeapify(arr, i, arr.length - 1)
}
return arr
}
// 构建小顶堆,实现倒序
function sortArr(arrList) {
buildMaxHeap(arrList)
for (let i = arrList.length -1 ; i > 0; i--) {
swap(arrList, 1, i)
//重新调整小顶堆
maxHeapify(arrList, 1, i - 1)
}
arrList.shift()
return arrList
}
// 构建小顶堆实现topK算法
function topK(list, k) {
let newStack = buildMaxHeap(list.slice(0, k))
for (let i = k, len = list.length; i < len; i++) {
if (newStack[1] < list[i]) {
newStack[1] = list[i]
maxHeapify(newStack, 1, k)
}
}
newStack.shift()
return newStack
}
10、koa中间件原理
class App {
constructor() {
this.mutationList = []
this.index = 0
}
use(fn) {
this.mutationList.push(fn)
}
compose() {
const mutationList = this.mutationList
// 递归函数
function dispatch(index) {
// 如果所有中间件都执行完跳出
if (index === mutationList.length) return;
// 取出第 index 个中间件并执行
const route = mutationList[index];
return route(() => dispatch(index + 1));
}
// 取出第一个中间件函数执行
dispatch(0);
}
composeReduce() { // 使用reduce函数
return this.mutationList.reduce((pre, n) => (args) => pre(() => n(args)))(() =>{})
}
}
11、嵌套过滤器、拦截器的原理
function c(num) {
return num + 'c'
}
function b(num) {
return num + 'b'
}
function a(num) {
return num + 'a'
}
function curry(...fns) {
if (!fns) return
return fns.reduce((pre, next) => {
return (...rest) => next(pre(...rest))
})
}
const test = curry(a, b, c)
console.log(test(1))// 输出1abc,按照顺序执行,前一个的执行结果是后一个函数的入参
12、写一个 mySetInterVal(fn, a, b), 每次间隔 a, a + b, a + 2b 的时间,然后写一个 myClear,停止上面的 mySetInterVal
function initInterval(fn, a, b) {
let count = 0
let timer = null
function createInterval() {
clearInterval(timer)
timer = setInterval(() => {
fn()
count++
createInterval()
}, a + count * b)
}
createInterval()
return timer
}
const timer = initInterval(() => { console.log('执行代码') }, 2000, 500)
13、手写节流函数
function throttle(fn, timeout, immediate, trailCall) {
let currentTime = 0
let lastTime = 0
let timer = null
return function (...args) {
let context = this
currentTime = +new Date()
if (timer) {
clearTimeout(timer)
}
if (immediate) {
immediate = false
fn.call(context, ...args)
lastTime = +new Date()
return
}
if (currentTime - lastTime >= timeout) {
fn.call(context, ...args)
lastTime = currentTime
}
if (trailCall) {
timer = setTimeout(() => {
fn.call(context, ...args)
lastTime = +new Date()
}, timeout)
}
}
}
14、把一个数组,分为n组,每组的和尽可能的接近或相等
/*
* 数组排序
* @arr 排序的数组
*/
const arrSort = (arr) => {
return arr.sort((a, b) => b - a)
};
/*
* 数组求和
* @arr 求和数组
*/
const sumTotal = arr => eval(arr.join('+'));
/*
* getEqualArr 获取均分的结果
* @arr 均分的整数数组
* @n 均分的份数
*/
const getEqualArr = (arr,n=3) => {
const sortArr = arrSort(arr);
const arrSum = sumTotal(arr);
let result = [];
(getEachArr = () => {
let startNum = 0;
let eactArr = [];
// 如果是最后一组,就直接push
if (result.length === n-1) {
result.push(sortArr);
return result;
} else {
sortArr.map((num, index) => {
if (startNum + num <= Math.ceil(arrSum / n)) {
startNum = startNum + num;
eactArr.push(...sortArr.splice(index, 1));
}
})
result.push(eactArr);
// 提取完一组接着再进行提取下一组
getEachArr();
}
})();
return result;
}
console.log(getEqualArr([1, 2, 3, 4, 5, 6, 7, 8])) // 输出[ [ 8, 4 ], [ 7, 5 ], [ 6, 3, 2, 1 ] ]
15、常见的排序算法(冒泡、快排、归并排、插入排) blog.csdn.net/w405722907/…
// 使用快排实现topk算法
function quickTopK(arr, k) {
if(k==0)return []
if (arr.length < 2 || arr.length <= k) return arr
let midValue = arr.splice(0, 1), left = [], right = []
arr.forEach((el) => {
el > midValue ? left.push(el) : right.push(el)
});
console.log(left, right)
if (left.length == k) {
return left
} else if (left.length > k) {
return quickTopK(left, k)
} else {
return left.concat(midValue, quickTopK(right, k - left.length - 1))
}
}
16、手写promise实现
const PENDING = 'pending'
const FULFILL = 'fuifilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) { // 传入一个回调函数
this._resolveQueue = []
this._rejectQueue = []
this._status = PENDING
this._value = ''
const _resolveFn = value => {
setTimeout(() => { // 防止先执行回调再then收集依赖
if (this._status !== PENDING) return
this._value = value
this._status = FULFILL
while(this._resolveQueue.length) {
const cb = this._resolveQueue.shift()
cb(value)
}
})
}
const _rejectFn = value => {
setTimeout(() => { // 防止先执行回调再then收集依赖
if (this._status !== PENDING) return
this._value = value
this._status = REJECTED
while(this._rejectQueue.length) {
const cb = this._rejectQueue.shift()
cb(value)
}
})
}
executor(_resolveFn, _rejectFn)
}
then(resolveFn, rejectFn) { // 为了实现链式调用,所以then方法需要return一个promise对象
typeof resolveFn !== 'function' ? resolveFn = value => value : null
typeof rejectFn !== 'function' ? rejectFn = reason => {
throw new Error(reason instanceof Error? reason.message:reason);
} : null
return new MyPromise((resolve, reject) => {
const fuifilledFn = value => {
try {
const x = resolveFn(value)
x instanceof MyPromise ? x.then(resolve) : resolve(x)
} catch(error) {
reject(error)
}
}
const rejectedFn = value => {
try {
const x = rejectFn(value)
x instanceof MyPromise ? x.then(resolve) : resolve(x)
} catch(error) {
reject(error)
}
}
switch(this._status) {
case PENDING:
this._resolveQueue.push(fuifilledFn)
this._rejectQueue.push(rejectedFn)
break;
case FULFILL:
fuifilledFn(this._value)
break;
case REJECTED:
rejectedFn(this._value)
}
})
}
}
17、sku算法[大神sku算法链接]juejin.cn/post/684490…