前端刷题 —— 牛客网前端题库60道详解(六)

1,583 阅读6分钟

目录

  • 引言

    1. 乘法 (入门)
    2. 改变上下文 (入门)
    3. 批量改变对象的属性 (入门)
    4. 属性遍历 (简单)
    5. 判断是否包含数字 (入门)
    6. 检查重复字符串 (简单)
    7. 判断是否以元音字母结尾 (入门)
    8. 获取指定字符串 (简单)
    9. 判断是否符合指定格式 (简单)
    10. 判断是否符合 USD 格式 (中等)

引言

牛客网这个前端笔试题库,可以说这60道是最基础的了,也是考察的东西比较杂,有时间4天差不多就可以刷完,巩固基础还是有些用的。做完题回顾一上午就可以过完一遍。现在我结合我的答案和参考的其他人的答案,在这里做一个总结,也是自己知识的整理结果。

51. 乘法

题目描述
求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题
输入:3, 0.0001
输出:0.0003

// 方法一:确定小数的位数然后保证精度是多少位
function multiply(a, b) {
    let arrA = a.toString().split('.')[1] || ''
    let arrB = b.toString().split('.')[1] || ''
    let fix = arrA.length + arrB.length
    return (a * b).toFixed(fix)
}

// 方法二:自己写的
function multiply(a, b) {
    let arrA = a.toString().split('.')
    let arrB = b.toString().split('.')
    let count = 0
    // 第一个有小数位
    if(arrA[1]) {
        count+=arrA.length
        a = a * Math.pow(10,arrA.length)
    }
    // 第二个数有小数位
    if(arrB[1]) {
        count+=arrB.length
        b = b * Math.pow(10,arrB.length)
    }
    return a * b * Math.pow(10, -count)
}

相关知识点:

  • javascript小数精度问题

javascript的数值存储是双精度浮点数64位,根据IEEE 754标准,0-51为值,52-62位指数,63位是符号位。
二进制浮点数表示法对0.1这样的有误差。
解决方法就是先升幂再降幂。

52. 改变上下文

题目描述
将函数 fn 的执行上下文改为 obj,返回 fn 执行后的值
输入: alterContext(function() {return this.greeting + ', ' + this.name + '!'; }, {name: 'Rebecca', greeting: 'Yo' })
输出:Yo, Rebecca!

// 方法一:call
function alterContext(fn, obj) {
    return fn.call(obj)
}

// 方法一:apply
function alterContext(fn, obj) {
    return fn.apply(obj)
}

// 方法一:bind
function alterContext(fn, obj) {
    return fn.bind(obj)()
}

相关知识点:

  • call/apply/bind

53. 批量改变对象的属性

题目描述
给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。
输入:

var C = function(name) {this.name = name; return this;};   
var obj1 = new C('Rebecca');   
alterObjects(C, 'What\'s up'); obj1.greeting;  

输出:What's up

// 方法一:原型对象上添加属性
function alterObjects(constructor, greeting) {
    constructor.prototype.greeting = greeting
}

相关知识点:

  • 原型链

54. 属性遍历

题目描述
找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)
1、返回数组,格式为 key: value
2、结果数组不要求顺序
输入

var C = function() {this.foo = 'bar'; this.baz = 'bim';}; 
C.prototype.bop = 'bip'; 
iterate(new C());

输出 ["foo: bar", "baz: bim"]

// 方法一: forEach换成map更好,这里不是重点所以不做处理
function iterate(obj) {
    let arr = []
    Object.getOwnPropertyNames(obj).forEach(value => arr.push(`${value}: ${obj[value]}`))
    return arr
}

相关知识点:

  • Object.getOwnPropertyNames(obj), 获取所有的对象自身属性

55. 判断是否包含数字

题目描述
给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false
输入: 'abc123' ; 输出: true

// 方法一:字符串比较ASCII码
function containsNumber(str) {
    for (let i = 0; i < str.length; i++) {
        if(str[i] >= '0' && str[i] <= '9') {
            return true
        }
    }
    return false
}

// 方法二:隐式类型转化
function containsNumber(str) {
    for (let i = 0; i < str.length; i++) {
        if(str[i] >= 0 || str[i] <= 9) {
            return true
        }
    }
    return false
}

// 方法三:正则
function containsNumber(str) {
    return /\d/g.test(str)
}

相关知识点:

  • 字符串比较ASCII码

字符串比较会比较他们的ASCII码值,数字是连续的ASCII码,0123456789分别是48-57,在这个范围内的就可以。

  • 隐式类型转化

数字字符串和数字比较,会隐式转化成数字,字符串和数字比较,会转化成数字NaN,和数字比较返回false,所以这种方式也可以找到字符串中是否有数字。

  • 正则

56. 检查重复字符串

题目描述
给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false
输入: 'rattler'
输出: true

// 方法一:双指针
function containsRepeatingLetter(str) {
    // 如果字符串长度小于2直接返回false
    if(str.length < 2)return false
    // 左右指针
    let left = 0
    let right = 1
    while(str[right]) {
        // 如果左右相等且都是a-z范围的就返回true
        if(str[left++] === str[right++] && str[left].toLowerCase() >= 'a' && str[left].toLowerCase() <= 'z' && str[right].toLowerCase() >= 'a' && str[right].toLowerCase() <= 'z'){
            return true
        }
    }
    // 否则返回false
    return false
    
}

// 方法二:正则,小括号表示分组,\1表示引用第一个分组
function containsRepeatingLetter(str) {
    return /([a-zA-Z])\1/.test(str);
}

相关知识点:

  • 双指针(算法思维)
  • 正则

57. 判断是否以元音字母结尾

题目描述
给定字符串 str,检查其是否以元音字母结尾
1、元音字母包括 a,e,i,o,u,以及对应的大写
2、包含返回 true,否则返回 false
输入: 'gorilla' ; 输出: true

// 方法一:indexOf
function endsWithVowel(str) {
    return ['a','e','i','o','u'].indexOf(str.slice(-1).toLowerCase()) === -1 ? false: true
}

// 方法二:includes
function endsWithVowel(str) {
    return ['a','e','i','o','u'].includes(str.slice(-1).toLowerCase())
}

相关知识点:

  • 字符串方法slice,toLowerCase
  • 数组方法indexOf,includes

58. 获取指定字符串

题目描述
给定字符串 str,检查其是否包含 连续3个数字
1、如果包含,返回最先出现的 3 个数字的字符串
2、如果不包含,返回 false
输入: '9876543'
输出: 987

PS: 这个题我们理解的是三个连续递增的数字,但是题的意思是连续的数字即可。

// 方法一:计数器
function captureThreeNumbers(str) {
  let start = 0
  let count = 0
  for(let i = 0; i < str.length; i++) {
    if (!isNaN(str[i])) {
      count++
    } else {
      count = 0
      start = i+1
    }
  }
  
  return count >= 3 ? str[start]+str[start+1]+str[start+2] : false
}

// 方法二:正则 match可以得到匹配的结果
function captureThreeNumbers(str) {
  let arr = str.match(/\d{3}/)
  return arr ? arr[0] : false
}

如果是连续递增的数字,要这样实现:

// 方法一:双指针
function captureThreeNumbers(str) {
    let left = 0
    let right = 0
    while(str[right+1] !== undefined) {
        // 保证右指针连续,且属于数字,右指针往过移动
        if(Math.abs(str[right+1] - str[right]) === 1 && str[right] >=0 && str[right] <=9) {
            right++
        // 如果小于3,左指针就去右指针右边
        }else if(right - left + 1 < 3){
            left = ++right
        // 大于3直接返回    
        }else {
            return str.substr(left,3)
        }
    }
    // 循环结果,如果大于3就返回,否则返回false
    return right - left + 1 >= 3 ? str.substr(left,3) : false
}

相关知识点:

  • 计数器
  • 正则
  • 双指针(算法思维) + 判断连续数字

59. 判断是否符合指定格式

题目描述
给定字符串 str,检查其是否符合如下格式
1、XXX-XXX-XXXX
2、其中 X 为 Number 类型
输入:'800-555-1212'
输出:true

// 方法一:正则
function matchesPattern(str) {
    return /^\d{3}-\d{3}-\d{4}$/.test(str)
}

相关知识点:

  • 匹配或者判断什么格式就优先考虑正则

60. 判断是否符合 USD 格式

题目描述
给定字符串 str,检查其是否符合美元书写格式
1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用 , 分隔
3、如果为小数,则小数部分长度为 2
4、正确的格式如:$1,023,032.03 或者 $2.03
错误的格式如:$3,432,12.12 或者 $34,344.3
输入:'$20,933,209.93'
输出:true

// 方法一:正则,从左往右写,依次匹配
function isUSD(str) {
    return /^\$[\d]{1,3}(\,[\d]{3})*(|\.[\d]{2})$/.test(str)
}

相关知识点:

  • 正则

已经到底拉,60道题完事,恭喜你,通关啦~~~~