今天浏览知乎上的一篇文章web前端大厂10道经典面试题汇总(含答案详解) ,自己照着思路尝试着写一版。
1、写一个js函数,实现对一个数字每3位加一个逗号,如输入100000, 输出100,000(不考虑负数,小数)—百度前端面试题 解题思路 将数字调用toString方法变成字符串,然后用split方法切割成数组;用reverse方法对数组进行倒序,用reduce方法对数组每3位后面添加“,”,最后再用reverse方法将数组倒序回来,并用join方法进行拼接。
1 2 3 4 5 6 const num = 100000 const arr = num.toString ().split ('' )const str = arr.reverse ().reduce ((acc, cur, index ) => { if (index % 3 === 0 ) { return `${acc} ,${cur} ` } else { return acc + cur } }).split ('' ).reverse ().join ('' ) console .log (str)
拓展 题目虽然说不考虑负数和小数,但如果考虑进去需要多做什么处理呢?
1、考虑负数:由于负数只会在最前面出现一次,所以只需要在整除3余数是否为零的条件下再多一个当前值cur是否为“-”即可,代码如下:
1 2 3 4 5 6 const num = -100000 const arr = num.toString ().split ('' )const str = arr.reverse ().reduce ((acc, cur, index ) => { if (index % 3 === 0 && cur !== '-' ) { return `${acc} ,${cur} ` } else { return acc + cur } }).split ('' ).reverse ().join ('' ) console .log (str)
2、考虑小数:以小数点为界限,切分整数部分和小数部分,整数部分按照原来的思路方法,最后把小数部分拼接回去即可,代码如下:
1 2 3 4 5 6 7 const num = -100000.12 const arr = num.toString ().split ('.' )const prevArr = arr[0 ].split ('' )const str = prevArr.reverse ().reduce ((acc, cur, index ) => { if (index % 3 === 0 && cur !== '-' ) { return `${acc} ,${cur} ` } else { return acc + cur } }).split ('' ).reverse ().join ('' ) + (arr[1 ] ? `.${arr[1 ]} ` : '' ) console .log (str)
总结 以上功能其实就是toLocalString方法的简单实现,实验中我发现,关于小数点后面如果是“.00”,在使用toString和toLocalString方法后都会自动去掉,并不会保留小数部分,代码如下:
1 2 3 4 5 6 7 8 const num = -100000.00 const arr = num.toString ().split ('.' )const prevArr = arr[0 ].split ('' )const str = prevArr.reverse ().reduce ((acc, cur, index ) => { if (index % 3 === 0 && cur !== '-' ) { return `${acc} ,${cur} ` } else { return acc + cur } }).split ('' ).reverse ().join ('' ) + (arr[1 ] ? `.${arr[1 ]} ` : '' ) console .log (num.toLocaleString ()) console .log (str)
这点不知道是不是我多虑了,不过我也试着想了一个不完美解决办法,一般这种情况可以直接调用toFixed方法保留小数点后几位(比如两位),再做下一步处理,代码如下:
1 2 3 4 5 6 7 const num = -100000.00 const arr = num.toFixed (2 ).split ('.' )const prevArr = arr[0 ].split ('' )const str = prevArr.reverse ().reduce ((acc, cur, index ) => { if (index % 3 === 0 && cur !== '-' ) { return `${acc} ,${cur} ` } else { return acc + cur } }).split ('' ).reverse ().join ('' ) + (arr[1 ] ? `.${arr[1 ]} ` : '' ) console .log (str)
2、给定一个字符串,找出其中无重复字符的最长子字符串长度—字节跳动前端面试题 解题思路 将字符串调用split方法切割成数组,用reduce方法对数组进行判断无重复拼接,通过判断当前字符是否存在,如果不存在则拼接,并保存字符串长度最大值,存在则删除重复字符串之前的字符,重新拼接新的字符串,最终获得最长的字符串长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 const str = 'abbbcbd' let len = 1 str.split ('' ).reduce ((acc, cur ) => { const idx = acc.indexOf (cur) if (idx === -1 ) { const noRepeatStr = acc + cur len = Math .max (len, noRepeatStr.length ) return noRepeatStr } else { return acc.substring (idx + 1 ) + cur } }) console .log (len)
拓展 题目只要最长字符串长度,如果需要找出这些最长字符串呢?
其实只需要在保存记录长度的时候,顺便保存一下字符串数组即可,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const str = 'abbbcbd' let len = 1 let arr = []str.split ('' ).reduce ((acc, cur ) => { const idx = acc.indexOf (cur) if (idx === -1 ) { const noRepeatStr = acc + cur if (noRepeatStr.length > len) { arr.push (noRepeatStr) } len = Math .max (len, noRepeatStr.length ) return noRepeatStr } else { return acc.substring (idx + 1 ) + cur } }) console .log (len) console .log (arr.filter (v => v.length === len))
总结 拓展里面返回的字符串是一个数组,这里说明一下,有可能存在长度相同的多个最长无重复字符串,因此需要一个数组来存储会比较合适。
实现超出整数存储范围的两个大正整数相加—腾讯前端面试题 解题思路 将两个大整数进行比较,对不足的位数进行补零,然后将其用split方法拆解成数组,并用reverse方法反转数组顺序,接着按位一一对应相加,注意进位即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 let a = '123123231231234444435' , b = '434235656455454543' const n1 = a.length , n2 = b.length const n = Math .max (n1, n2)for (let i = 0 ; i < n - Math .min (n1, n2); i++) { if (n1 > n2) b = '0' + b if (n1 < n2) a = '0' + a } a = a.split ('' ).reverse () b = b.split ('' ).reverse () let res = Array .from ({ length : n }, v => 0 )for (let k = 0 ; k < n; k++) { const temp = parseInt (a[k]) + parseInt (b[k]) if (temp > 9 ) { res[k] += temp - 10 res[k + 1 ] = 1 } else { res[k] += temp } } res = res.reverse ().join ('' ) console .log (res)
拓展 首先了解超出存储范围的大数字概念,每种数据类型可存储数据量都是存在范围的
数字类型的范围:
Number.MAX_VALUE = 1.7976931348623157e+308
Number.MIN_VALUE = 5e-324
整数类型的范围:-2^-53 - 2^53
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
第1位:符号位,0表示正数,1表示负数 第2位到第12位(共11位):指数部分 第13位到第64位(共52位):小数部分(即有效数字) 符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。
指数部分一共有11个二进制位,因此大小范围就是0到2047。IEEE 754 规定,如果指数部分的值在0到2047之间(不含两个端点),那么有效数字的第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字这时总是1.xx…xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript 提供的有效数字最长为53个二进制位。
1 (-1)^符号位 * 1.xx...xx * 2^指数部分
这里还有一篇关于IEEE 754的详细介绍,有兴趣的可以看看IEEE 754浮点数标准详解
4、任意二维数组的全排列组合—阿里巴巴前端面试题 解题思路 把多项数组逐步两两相乘的方式,第一次先取二维数组前两项组合,把组合的结果在与第三项组合以此类推。这种递归做法简单易懂,把复杂的多项问题简化成两项问题的逐渐递增。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const exchange = (arr ) => { const len1 = arr[0 ].length const len2 = arr[1 ].length const lenBoth = len1 * len2 let items = new Array (lenBoth), index = 0 for (let i = 0 ; i < len1; i++) { for (let j = 0 ; j < len2; j++) { items[index] = arr[0 ][i] + ',' + arr[1 ][j] index++ } } arr.shift () arr[0 ] = items if (arr.length > 1 ) { return exchange (arr) } else { return arr[0 ] } } const array = [['A' , 'B' , 'C' ], ['A1' , 'B1' , 'C1' ], ['A2' , 'B2' ]]console .log (exchange (array))
5、公司最近新研发了一种产品,共生产了n件。有m个客户想购买此产品,已知每个顾客出价。为了确保公平,公司决定要以一个固定的价格出售产品。每一个出价不低于要价的客户将会得到产品(每人只买一个),余下的将会被拒绝购买。请你找出能让公司利润最大化的售价。—京东前端面试题 解题思路 本题是京东的业务演变题,首先要理清思路。本题中,固定出价,以及出价低于产品的顾客会被拒绝购买是解题核心。
条件中已知产品总个数,顾客出价。这里有个小陷阱,会出现N < M供不应求的情况,要特殊考虑。依据题目,我们首先需要对顾客出价排序,这里按升序排列。当供不应求出现时,我们截取出价高的顾客。然后把每个顾客的出价当做最终售价循环,得出最大化利润下的售价。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const getOptimal = (n, m, arr ) => { let key = 0 , max = 0 arr = arr.sort ((a, b ) => a - b) if (n < m) arr = arr.slice (m - n) for (let i = 0 ; i < arr.length ; i++) { if (max < arr[i] * (arr.length - i)) { max = arr[i] * (arr.length - i) key = arr[i] } } return key } const n = 3 , m = 4 , arr = [2 , 8 , 10 , 7 ]console .log (getOptimal (n, m, arr))
6、计算出字符串中出现次数最多的字符是什么,出现了多少次?—华为前端面试题 解题思路 计算出全部字符出现次数,并留下最大的。首先利用filter()与indexOf()的方法连用字符串去重,再将得到的作为索引,利用split()分割字符串,得到字符出现次数,比较得出结果。
1 2 3 4 5 6 7 8 9 10 11 const str = 'abbbcbd' let count = 0 , char = '' const arr = [...new Set (str.split ('' ))]for (let i = 0 ; i < arr.length ; i++) { const n = (str.split (arr[i])).length - 1 if (count < n) { count = n char = arr[i] } } console .log (count, char)
7、”123456789876543212345678987654321…”的第n位是什么?—小米面试题 解题思路 利用数学中最小循环节的概念解题,找到最小循环节后,利用余数查找第n位数字。
1 2 3 4 5 const k = '1234567898765432' const getNum = (n ) => { return k.charAt (n % k.length - 1 ) } console .log (getNum (20 ))
8、请编写一个 JavaScript 函数 parseQueryString,它的用途是把 URL 参数解析为一个对象—淘宝面试题 解题思路 淘宝这道题是很常用的场景题,这里需要处理好分段次序,首先把?分离,然后按&分割最后按=分割,主要考察字符串的函数运用以及对象的创建。
1 2 3 4 5 6 7 8 9 10 const parseQueryString = (url ) => { const arr = url.split ('?' )[1 ].split ('&' ) let obj = {} for (let i = 0 ; i < arr.length ; i++) { const value = arr[i].split ('=' ) obj[value[0 ]] = value[1 ] } return obj } console .log (parseQueryString ('https://www.baidu.com/s?wd=shiyuanjieyi&rsv_spt=1&rsv_iqid=0xb198d7d800011de6&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_sug3=14&rsv_sug1=13&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&inputT=29439&rsv_sug4=29439' ))
9、如果给定的字符串是回文,返回true,反之,返回false。回文:如果一个字符串忽略标点符号、大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文)。—网易前端面试题 解题思路 去掉字符串多余的标点符号和空格,然后把字符串转化成小写来验证此字符串是否为回文。
1 2 3 4 5 6 const palindrome = (str ) => { const str1 = str.replace (/[^0-9a-zA-Z]/g , '' ).toLowerCase () const str2 = str1.split ('' ).reverse ().join ('' ) return str1 === str2 } console .log (palindrome ('aBc,./1d42--==EFG0 00 h0 :00gfE24d 1cBA' ))
10、确保字符串的每个单词首字母都大写,其余部分小写。——搜狐前端面试题 解题思路
字符串转化成小写;
分割成字符串数组;
新组合字符串元素=首字母转大写+其余小写。
1 2 3 4 5 const upperCase = (str ) => { const arr = str.toLowerCase ().split (' ' ) return arr.map (v => v[0 ].toUpperCase () + v.slice (1 )).join (' ' ) } console .log (upperCase ("I'm a title Case." ))
(完)
评论加载中