这种题目,除了多练,没别的方法
1. 实现一个类似 emiter 的类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 class EventEmiter { constructor ( ) { this .emiterMap = {} } on (event, callback ) { if (this .emiterMap [event]) { this .emiterMap [event].push (callback) } else { this .emiterMap [event] = [callback] } } emit ( ) { let [event, ...args] = [...arguments ] this .emiterMap [event] && this .emiterMap [event].forEach ((callback ) => callback (...args)) } off (event, callback ) { this .emiterMap [event] = this .emiterMap [event].filter ((cb ) => cb != callback) } once (event, callback ) { let fn = (...args ) => { callback (args) this .off (event, fn) } this .on (event, fn) } } let em = new EventEmiter ()var work1 = function ( ) { console .log ('work1' ) } var work2 = function ( ) { console .log ('work2' ) } var once1 = function ( ) { console .log ('once1' ) } em.on ('work1' , work1) em.on ('work2' , work2) em.emit ('work1' ) em.emit ('work1' ) em.emit ('work2' ) em.emit ('work2' ) em.once ('once' , once1) em.emit ('once' ) em.emit ('once' ) em.emit ('once' ) em.emit ('once' ) em.emit ('once' ) em.emit ('once' ) var day = 18 em.on ('addday' , function ( ) { let [...args] = [...arguments ] console .log ('in add arg: ' , args[0 ], args[1 ]) day = day + Number (args[0 ]) + Number (args[1 ]) console .log ('add day: ' , day) }) em.on ('subday' , function ( ) { day = day - 5 }) em.on ('logday' , function ( ) { console .log (day) }) em.emit ('addday' , 10 , 20 ) em.emit ('subday' ) em.emit ('logday' )
2. 函数柯里化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function add ( ) { var _args = Array .prototype .slice .call (arguments ) var _addr = function ( ) { _args.push (...arguments ) return _addr } _addr.toString = () => _args.reduce ((total, num ) => total + num) return _addr } console .log (add (1 , 2 , 3 )(4 )(5 ))
3. 快速排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function quickSort (arr ) { if (arr.length <= 1 ) { return arr } var pivotIdx = Math .floor (arr.length / 2 ) var pivot = arr.splice (pivotIdx, 1 )[0 ] var left = [] var right = [] for (let index = 0 ; index < arr.length ; index++) { const element = arr[index] if (element < pivot) { left.push (element) } else { right.push (element) } } return quickSort (left).concat ([pivot], quickSort (right)) } console .log (quickSort ([2 , 4 , 1 , 7 , 3 , 5 ]))
4. 实现一个 calc 方法 可以将输入的数拆解为尽可能多的乘数,所有数相乘等于输入数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 function isPrime (num ) { for (let i = 2 ; i <= Math .sqrt (num); i++) { if (num % i == 0 ) { return false } } return true } function calc (n ) { let list = [] while (n > 1 ) { for (let i = 2 ; i <= n; i++) { if (isPrime (i) && n % i === 0 ) { list.push (i) n /= i } } } return list } console .log (calc (2 ))console .log (calc (8 ))console .log (calc (24 ))console .log (calc (30 ))
5. 多维数组扁平化 1 2 3 4 5 6 7 8 function flatDeep (arr ) { return arr.reduce ( (acc, curr ) => (Array .isArray (curr) ? acc.concat (flatDeep (curr)) : acc.concat (curr)), [] ) } let a = [1 , 2 , 3 , [4 , 5 , 6 , [7 , 8 ], 9 ], 10 ]console .log (flatDeep (a))
6. 击鼓传花 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 let players = [ 'n1' , 'n2' , 'n3' , 'n4' , 'n5' , 'n6' , 'n7' , 'n8' , 'n9' , 'n10' , 'n11' , 'n12' , 'n13' , 'n14' , 'n15' , ] class Queue { constructor ( ) { this .queueList = [] } addItem (item ) { this .queueList .push (item) } delItem (item ) { return this .queueList .shift () } size ( ) { return this .queueList .length } } function findPepole (arr, num ) { let myQueue = new Queue () for (let i = 0 ; i < arr.length ; i++) { const element = arr[i] myQueue.addItem (element) } let eliminated = '' while (myQueue.size () > 1 ) { for (let i = 0 ; i < num; i++) { myQueue.addItem (myQueue.delItem ()) } eliminated = myQueue.delItem () console .log (eliminated + ' 在击鼓传花游戏中被淘汰。' ) } return myQueue.queueList } let victor = findPepole (players, 3 )[0 ]console .log (`胜利者是: ${victor} ` )
主要思路就是, 一个一个删,如果删除的那一个不是指定位置的那一个,就放到最后边,如果是, 就直接删除,直到数组只有一个了
7. 两个数组求交集 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let list1 = [1 , 2 , 3 , 4 , 4 , 5 ]let list2 = [4 , 4 , 5 , 6 , 7 , 8 ]function intersection (arr1, arr2 ) { let tempList = [] for (let i = 0 ; i < arr1.length ; i++) { const element = arr1[i] if (arr2.includes (element)) { tempList.push (element) } } return tempList } console .log (intersection (list1, list2))
8. 求字符串数组的最长公共前缀 比如输入: [“flower”,”flow”,”flight”],输出: “fl”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let longestCommonPrefix = function (strs ) { if (strs.length === 0 ) return '' if (strs.length === 1 ) return strs[0 ] let tempStr = strs[0 ] for (let i = 0 ; i < strs.length ; i++) { let j = 0 for (; j < strs.length && j < tempStr.length ; j++) { if (tempStr.charAt (j) !== strs[i].charAt (j)) { break } } tempStr = tempStr.substring (0 , j) } return tempStr } let commonStr = longestCommonPrefix (['flower' , 'flow' , 'flight' ])console .log (commonStr)
9. 合并两个数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 let a = [1 , 2 , 3 ]let b = [4 , 5 , 6 ]let c = a.concat (b)console .log (c, a, b)
10. 实现一个 PromiseLinit 根据 urls 数组内的 url 地址进行并发网络请求,最大并发数 maxNumber,当所有请求完毕后调用 callback 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 function fetch (url ) { return new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('ok ' + url) }, Math .floor (Math .random () * 1000 ) + 600 ) }) } function PromiseLinit (urls, limit, callback ) { let result = [] let urlsLen = urls.length let i = 0 while (i < limit) { next () } function next ( ) { let current = i++ if (current >= urlsLen) { result.length === urlsLen && callback (result) return } console .log (`${current + 1 } 开始` ) fetch (urls[current]) .then ((res ) => { console .log (`${current + 1 } 成功结束` ) result.push (res) if (current < urlsLen) { next () } }) .catch ((err ) => { console .log (`${current + 1 } 失败结束` ) result.push (res) if (current < urlsLen) { next () } }) } } let urls = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 ]PromiseLinit (urls, 4 , (res ) => { console .log ('success: ' , res) })
11. 求 left, right 最终宽度 11.1 算收缩 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <!DOCTYPE html > <html lang ="en" > <body > <div class ="container" > <div class ="left" > </div > <div class ="right" > </div > </div > </body > <style > * { padding : 0 ; margin : 0 ; } .container { width : 600px ; height : 300px ; display : flex; } .left { flex : 1 2 500px ; background : red; } .right { flex : 2 1 400px ; background : blue; } </style > </html >
子项的收缩宽度 = 子项收缩比例 X 溢出宽度 子项收缩比例 = 子项宽度 X 子项收缩系数 / 所有子项的(宽度 X 系数)之和
对应题目:
子项溢出空间的宽度为 $500 + 400 - 600 = 300$ left 收缩比例:$(500 × 2) ÷ (500 × 2 + 400 × 1) ≈ 0.7143$ right 收缩比例:$(400 × 1) ÷ (500 × 2 + 400 × 1) ≈ 0.2857$ 对应的:
left 收缩宽度:$0.7143 × 300 = 214.29$ right 收缩宽度:$0.2857 × 300 = 85.71$ 所以:
left 最终宽度:$500 - 214.29 = 285.71$ right 最终宽度:$400 - 85.71 = 314.29$
11.2 算扩展 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <!DOCTYPE html > <html lang ="en" > <body > <div class ="container" > <div class ="left" > </div > <div class ="right" > </div > </div > </body > <style > * { padding : 0 ; margin : 0 ; } .container { width : 600px ; height : 300px ; display : flex; } .left { flex : 1 2 300px ; background : red; } .right { flex : 2 1 200px ; background : blue; } </style > </html >
left 最终宽度:300 + (1/3) _ (600 - (300 + 200)) = 333.33 right 最终宽度:200 + (2/3) _ (600 - (300 + 200)) = 266.66
12. 实现一个 promise.all 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 function isPromise (obj ) { return ( obj && (typeof obj === 'object' || typeof obj === 'function' ) && typeof obj.then === 'function' ) } function myPromiseAll (arr ) { let requests = [] return new Promise ((resolve, reject ) => { arr.map ((item, idx ) => { if (isPromise (item)) { item .then ((result ) => { requests[idx] = result if (requests.length === arr.length ) { resolve (requests) } }) .catch ((err ) => { reject (err) }) } else { requests[idx] = item } }) }) } let p1 = Promise .resolve (3 )let p2 = 1337 let p3 = new Promise ((resolve, reject ) => { setTimeout (resolve, 100 , 'foo' ) }) myPromiseAll ([p1, p2, p3]).then ((values ) => { console .log (values) })
13. 字符串排序 在一个字符串数组中有红、黄、蓝三种颜色的球,且个数不相等、顺序不一致,请为该数组排序。使得排序后数组中球的顺序为:黄、红、蓝。
例如:红蓝蓝黄红黄蓝红红黄红,排序后为:黄黄黄红红红红红蓝蓝蓝。
1 2 3 4 5 6 7 8 9 10 11 12 let str1 = '红蓝蓝黄红黄蓝红红黄红' let obj = {红: 1 , 蓝: 2 , 黄: 3 }let str2 = st1 .split ('' ) .sort ((a, b ) => { return obj[a] - obj[b] }) .join ('' ) console .log (str2)
14. 数组转树,并去重 如何将 [{id: 1}, {id: 2, pId: 1}, …] 的重复数组(有重复数据)转成树形结构的数组 [{id: 1, child: [{id: 2, pId: 1}]}, …] (需要去重)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const arr = [{id : 1 }, {id : 2 , pId : 1 }, {id : 3 , pId : 2 }, {id : 4 }, {id : 3 , pId : 2 }, {id : 5 , pId : 4 }]const map = arr.reduce ((res, item, curIdx ) => ((res[item.id ] = Object .assign ({}, item)), res), {})let res = []for (const item of Object .values (map)) { if (item.pId ) { const parent = map[item.pId ] parent.child = parent.child || [] parent.child .push (item) } else { res.push (item) } } console .log ('res: ' , JSON .stringify (res))
15. 树转数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 const data = [ { id : 1 , pid : 0 , name : 'no.1' , children : [ { id : 2 , pid : 1 , name : 'no.2' , children : [ {id : 6 , pid : 2 , name : 'no.6' }, {id : 7 , pid : 2 , name : 'no.7' }, {id : 8 , pid : 2 , name : 'no.8' }, ], }, { id : 3 , pid : 1 , name : 'no.3' , children : [ {id : 9 , pid : 3 , name : 'no.9' }, {id : 10 , pid : 3 , name : 'no.10' }, {id : 11 , pid : 3 , name : 'no.11' }, ], }, { id : 4 , pid : 1 , name : 'no.4' , children : [ {id : 12 , pid : 4 , name : 'no.12' }, { id : 13 , pid : 4 , name : 'no.13' , children : [{id : 14 , pid : 13 , name : 'no.14' }], }, ], }, {id : 5 , pid : 1 , name : 'no.5' }, ], }, ] function treeToArray (list, newArray = [] ) { list.forEach ((item ) => { if (item.children ) { const tempItem = item.children delete item.children newArray.push (item) if (tempItem.length > 0 ) { return treeToArray (tempItem, newArray) } } newArray.push (item) }) return newArray } console .log ('newArray: ' , treeToArray (data))
16. 斐波那契数列 给一个 n 得到一个斐波那契数列数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 let fibonacci = (function (n ) { var cache = {} return function (n ) { if (n === 1 || n === 2 ) return 1 if (cache[n]) return cache[n] return (cache[n] = fibonacci (n - 1 ) + fibonacci (n - 2 )) } })() function getFibArray (n ) { let res = [] for (let i = 1 ; i <= n; i++) { res.push (fibonacci (i)) } return res } let t1 = new Date ().getTime ()console .log (getFibArray (33 ))let t2 = new Date ().getTime ()console .log (t2 - t1)
17. 深拷贝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 function deepClone (obj ) { if (typeof obj === 'object' ) { const temp = Array .isArray (obj) ? [] : {} for (let key in obj) { if (obj.hasOwnProperty (key)) { if (typeof obj[key] === 'object' ) { temp[key] = deepClone (obj[key]) } else { temp[key] = obj[key] } } } return temp } return obj } let ahui = { name : 'ahui' , age : '18' , city : ['泰国' , '新加坡' , '印度尼西亚' ], sayname : function ( ) { return this .name }, saycity : function ( ) { return this .city }, } let angeli = deepClone (ahui)angeli.name = 'angeli' console .log (ahui.sayname ())console .log (angeli.sayname ())angeli.city = ['深圳' , '娄底' ] console .log (ahui.saycity ())console .log (angeli.saycity ())
数组求子集 [1, 2, 3]
的所有子集是: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let arr = [1 , 2 , 3 ]function allSubsets (a ) { let res = [[]] for (let i = 0 ; i < a.length ; i++) { const tempRes = res.map (subset => { const item = subset.concat ([]) item.push (a[i]) return item }) res = res.concat (tempRes) } return res } console .log (allSubsets (arr));
二分法查数