美文网首页
九道前端数据类型转换笔试题

九道前端数据类型转换笔试题

作者: 24_Magic | 来源:发表于2019-05-12 15:46 被阅读0次

1.写一个js函数,实现给出一个数字每三位加一个逗号,如输入100000,输出100,000,不考虑负数和小数。 (百度前端面试题)
解法一:
分析:
其实这是number.toLocaleString()输出的结果,包括负数和小数(小数保留三位有效数字)

var num1 = 1234567;
var num2 = -1234567;
var num3 = 1234.5678;
console.log(num1.toLocaleString()) //1,234,567
console.log(num2.toLocaleString()) //-1,234,567
console.log(num3.toLocaleString()) //1,234.568

解法二:
分析:
1234567使用正则匹配,/((?<=\d)\d{3})+\b/g匹配到3n的字符串234567,用/\d{3}/g匹配到234567,使用数组的map方法转换成,234,567,与剩余的1进行拼接

function getNum(num) {
  if(!num) return
  let str = parseInt(num).toString()
  let re1 = /((?<=\d)\d{3})+\b/g
  let re2 = /\d{3}/g
  let str1 = str.match(re1)[0] //'234567'
  let str2 = str1.match(re2).map((el, index)=> {
    return ',' + el
  }).join('') //',234,567'
  let str3 = str.replace(str1, '') //'1'
  return str3 + str2
}
getNum(1234567) //'1,234,567'

解法三:
主要利用到string.slice(-3)依次获取字符串的后三位并存到一个新数组中,
递归直至string的长度小于3,这时候数组存放的是一个个倒序的三位字符串(除了最后一个元素),
然后利用array.reverse().join(',')转换成我们需要的字符串

function toBeLocaleString(num = Number) {
  let str = parseInt(num).toString()
  let arr = []
  s(str, arr)
  console.log(arr.reverse().join(','))
}
function s(str = String, arr = Array) {
  let strLen = str.length
  let arrLen = arr.length
  if (strLen > 3) {
    arr[arrLen] = str.slice(-3)
    str = str.slice(0,  - 3)
    s(str, arr)
  }else {
    arr[arrLen] = str
  }
}
toBeLocaleString(1234567) //

解法四:
分析:对数字直接操作,链式调用不同数据类型操作的API,返回所需的结果,注意链式调用时每一步的返回值

function localeStr(num) {
  if(!num) return 
  return num
    .toString()
    .split('')
    .reverse()
    .map((item, index) => {
      return index !=0 && index % 3 === 0 ? `${item},` : item
    })
    .reverse()
    .join('')
}
localeStr(1234567) //'1,234,567'

2.给定一个字符串,找出其中无重复字符的最长子字符串的长度(字节跳动前端面试题)
解法一:
分析:
比如字符串为abcdebcdx,我们在找这段字符串的不重复的最长子字符串的时候,是从开头第一个元素开始往后遍历,如果发现位置index处的字符str跟已经遍历的字符串重复,我们就把之前遍历的重复处的字符repeatStr去掉,从后一位开始组成我们的无重复子字符串resultStrfor循环到字符串的长度totalStrLen结束。

function filter(str = String) {
  let strLen = str.length
  let newStr = ''
  let newStrLen = Number
  for (let i = 0; i < strLen; i++) {
    //_str为str中i处的字符
    let _str = str.charAt(i)
    //index为_str在新字符串中的索引值,如果值为-1,则表示未重复
    let index = newStr.indexOf(_str)
    if (index === -1) {
      newStr += _str 
      newStrLen = newStrLen > newStr.length ? newStrLen : newStr.length
    } else {
      newStr = newStr.substr(index+1) + _str 
    }
  }
  return newStrLen
}
filter('abcdedaxab') //5

3.实现超出整数范围的两个大正整数相加(腾讯面试题)
分析:
每种数据类型都是有存储范围的
Number.MAX_VALUE = 1.7976931348623157e + 308
Number.MIN_VALUE = 5e - 324
整数类型范围为:-2的负53次方 - 2的53次方
在超出整数范围时,我们采用其他方式运算。首先,我们将两个整数变成相同位数的字符串,将较小的那个前面添加0占位,并逆排序。然后运用数组的方式将两个数组里面的元素对应相加,注意进位,生成新的数组,再将新的数组转换成字符串,最后反转字符串。

function addBigInt (a, b) {
  let n1 = a.length
  let n2 = b.length
  let n = Math.max(n1, n2) - Math.min(n1, n2)
  let nMax = Math.max(n1, n2)
  //将两个字符串变成相同位数
  for (let i = 0; i < n; i++) {
    if (n1 > n2) b = '0' + b
    if (n1 < n2) a = '0' + a
  }
  //将字符串变成数组并逆排序
  let arr1 = a.split('').reverse()
  let arr2 = b.split('').reverse()
  //生成项数为nMax,各项为0的数组
  let arr = Array.apply(this, Array(nMax)).map((item, index) => {
    return 0
  })
  //进位+1,保存到后一位数中
  for (let j = 0; j < nMax; j++) {
    let addNum = Number(arr1[j]) + Number(arr2[j])
    if (addNum > 9) {
      arr[j] += addNum - 10 
      arr[j + 1] = 1
    } else {
      arr[j] += addNum
    }
  }
  return arr.reverse().join('')
}
let a = '123456789'
let b = '56789'
addBigInt(a, b) //'123513578'

4.计算出字符串中出现次数最多的字符是什么,出现了几次?(华为面试题)
解法一:
分析:我们可以通过正则的match方法获取某个字符重复的次数,然后使用replace(re, '')方法,将已经检测过的重复字符用空字符串去掉,re指的是某个字符,最后比较哪个字符重复的次数最多就可以了。

function getRepeatStr(str) {
  let count = 0
  let char = ''
  let strLen = str.length
  while(str) {
    let tempChar= str.charAt(0)
    let re = new RegExp(tempChar, 'g')
    let tempCount = str.match(re).length
    if(tempCount > count) {
      count = tempCount
      char = tempChar
    }
    str = str.replace(re, '')
  }
  if (!str)  return {count, char}
}
getRepeatStr('sddffgghhjknvbgghffrrrrrr') //{count: 6, char: 'r'}

解法二:
分析:
利用Array.filter((el, index, array) => {})去重字符串,保存到新数组,遍历字符串,然后使用string.split(arr[i]).length - 1获取每个字符的个数,比较得到最多的那个字符和个数。

function getRepeatStr2(str) {
  let count = 0
  let char = ''
  let arr = str.split('')
  let noRepeatArr = arr.filter((el, index, array) => {
    //输出第一次出现的字符
    return array.indexOf(el) === index
  })
  //利用noRepeatArr里的字符分割str,得到的数组长度-1就是每个字符重复的个数
  let len = noRepeatArr.length
  for (let i = 0; i < len; i++) {
    let tempChar = noRepeatArr[i]
    let tempCount = str.split(tempChar).length -1
    if (tempCount > count) {
      count = tempCount
      char = tempChar
    }
  }
  if (char) return {char, count}
}
getRepeatStr2('aaadfffghhjjkkkkkkk') // {char: 'k', count: 7}

5.公司最近新研发了一种产品,共生产了n件。有m个客户想购买此产品,已知每个顾客出价。为了确保公平,公司决定要以一个固定的价格出售产品。每一个出价不低于要价的顾客将会得到产品(每人只买一个),余下的将会被拒绝购买。请你找出能让公司利润最大化的售价。(京东前端面试题)
分析:
假设顾客出价为[2, 8, 7, 10],利润就等于我们的售价price * (比这个售价高的顾客个数),比如售价为2,利润就等于 2 * 4 = 8;售价为7,利润就等于7 * 3 = 21,所以只要比较这个售价 * 该售价以上的顾客数这个值,取最大值的售价即时我们的售价,注意考虑n < m的情况,供不应求时,我们需要截取出价高的顾客出价。

function getBestPrice (n, arr) {
  let m = arr.length
  let bestPrice = 0
  let maxProfit = 0
  if (n < m) {
    arr = arr.slice(m - n) //截取出价高的人 arr.length === n
  }
  arr = arr.sort((a, b) => {
    return a-b //需对价格进行升序排列
  })
  let len = arr.length
  for (let i = 0; i < len; i++) {
    let price = arr[i]
    let profit= price  * (len - i) 
    if (profit > maxProfit) {
      maxProfit = profit
      bestPrice = price
    }
  }
  if (bestPrice) return {bestPrice, maxProfit}
}
getBestPrice(3, [2, 8, 7, 10]) //

6.'123456789876543212345678987654321...'的第n位是什么?(小米面试题)
分析:
可以看到循环体为'1234567898765432',利用数学的最小循环节解,用n除于循环节的余数求解

function getNum (n, str) {
  return str.charAt(n % str.length -1)
}
getNum (20, '1234567898765432') //

7.请编写一个Javascript函数parseQueryString,它的用途是把url参数解析为一个对象。(淘宝面试题)
分析:
本题主要是知道url的参数是通过什么分割的,首先用?分割,然后用&分割,最后用=分割

function parseQueryString (url) {
  let obj = {}
  let key = ''
  let value = ''
  let arr = url.split('?')[1].split('&')
  arr
    .map((el, index) => {
      return el.split('=')
    })
    .forEach((el, index) => {
      key = el[0]
      value = el[1]
      obj[key] = value
    })
  return obj
}
parseQueryString('https://imooc.com?user=Mike&age=27&sex=male') 
//{user: "Mike", age: "27", sex: "male"}

8.如果给定字符串是回文,返回true;反之,返回false。回文:如果一个字符串忽略标点符号、大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文)。(网易前端面试题)
分析:
首先利用正则去除掉标点符号和空格,将字符串变成小写,然后将字符串转换成数组,利用数组的反转,再转换成新的字符串同原来字符串比较是否一致。

function palindrome (str) {
  let re = /[^0-9a-zA-Z]/g
  let newStr = str.replace(re, '').toLowerCase() //获取小写后的无标点和空格的字符串
  let reverseStr = newStr.split('').reverse().join('') //反转字符串
  if (reverseStr === newStr) {
    return true
  } else {
    return false
  }
}
palindrome('  -- +=123?ua  --*% A-u=3@21') //true

9.确保字符串的每个单词的首字母都大写,其余部分小写。
分析:
利用正则直接筛选出每个单词,再将所得数组每个元素变成小写,每个元素的第一个字符变成大写,最后还原成字符串。

function titleCase (str) {
  let re = /\S+/g
  let arr = str.match(re)
  let newArr = arr.map((el, index) => {
    let lowerEl = el.toLowerCase()
    let upperEl = lowerEl .charAt(0).toUpperCase()
    return upperEl + lowerEl.substr(1)
  })
  return newArr.join(' ')
}
titleCase("I'm a good boy.\n Ok!") //"I'm A Good Boy. Ok!"

相关文章

网友评论

      本文标题:九道前端数据类型转换笔试题

      本文链接:https://www.haomeiwen.com/subject/edezoqtx.html