每日一道面试题
前言
由git仓库:https://github.com/Advanced-Frontend/Daily-Interview-Question提供的面试问题,做一个自己的每日答题记录。
先将已有的放上来,有的问题是选择性记录的。
55题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 第 55 题:某公司 1 到 12 月份的销售额存在一个对象里面,
如下:{ 1: 222, 2: 123, 5: 888 } ,
请把数据处理为如下结构:[222, 123, null, null, 888, null, null, null, null, null, null, null]。
*/
// 自己写的 low B function
function objToArr (obj) {
let ary = new Array(12).fill(null)
ary.forEach((el, index, ary) => {
ary[index] = obj[index + 1] ? obj[index + 1] : null
// console.log(el);
})
return ary
}
console.log(objToArr({ 1: 222, 2: 123, 5: 888 }))
// 大佬们写的 NB function
function objToArrNB (obj) {
return Array.from({ ...obj, length: 13 }).slice(1)
// retrun Array.from({length: 12}, (el, index) => (obj[index + 1] || null))
}
console.log(objToArrNB({ 1: 222, 2: 123, 5: 888 }))
56题
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
// 选择排序
function selectSort (ary) {
for (let i = 0; i < ary.length; i++) {
let min = ary[i]
let pos = i
for (let j = i + 1; j < ary.length; j++) {
if (min > ary[j]) {
pos = j
min = ary[j]
}
}
[ary[i], ary[pos]] = [ary[pos], ary[i]]
}
return ary
}
console.log(selectSort([1, 2, 3, 1, 2, 3, 4, 5, 6, 2, 3, 4, 1, 1, 2, 9]))
// 冒泡排序
function bubbleSort (ary) {
for (let i = ary.length; i > 1; i--) {
for (let j = 0; j < i; j++) {
if (ary[j] > ary[j + 1]) {
[ary[j], ary[j + 1]] = [ary[j + 1], ary[j]]
}
}
}
return ary
}
console.log(bubbleSort([1, 2, 3, 1, 2, 3, 4, 5, 6, 2, 3, 4, 1, 1, 2, 9]))
59题
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
/* 第 59 题:给定两个数组,写一个方法来计算它们的交集。
例如:给定 nums1 = [1, 2, 2, 1],nums2 = [2, 2],返回 [2, 2]。 */
// 思路:遍历数组1,对每个元素判断其是否在数组2中,存在则提出来放到一个新数组里,并且从数组2中剔除,以确保下一次遍历不会出现重复的。
// 由于Array.splice()函数效率比较低,所以采用空间换取时间的方式,剔除的过程是将其他非交集元素放到新数组里。
// 想了想,还是用简单的splice吧。
function intersect (ary1, ary2) {
let longAry, shortAry
// 不取长短数组也行吧。
if (ary1.length > ary2.length) {
longAry = ary1
shortAry = ary2
} else {
longAry = ary2
shortAry = ary1
}
let tmpAry = []
try {
longAry.forEach(el => {
if (shortAry.length === 0) {
throw new Error('short array.lenth === 0')
}
let index = shortAry.indexOf(el)
if (index > -1) {
// 短数组中存在元素的情况
shortAry.splice(index, 1)
tmpAry.push(el)
}
})
} catch (error) {
console.log(error)
}
return tmpAry
}
console.log(intersect([1, 2, 2, 1], [2, 2]))
// 一种hash表的写法,时间复杂度也降下来了
// 先遍历数组1,存个hash表,保存值和出现的次数
// 再遍历数组2,如果hash表里有这个元素,就放到result数组里,并把出现次数-1;
const intersect = (nums1, nums2) => {
const map = {}
const res = []
for (let n of nums1) {
if (map[n]) {
map[n]++
} else {
map[n] = 1
}
}
for (let n of nums2) {
if (map[n] > 0) {
res.push(n)
map[n]--
}
}
return res
}
67题
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
// 第 67 题:随机生成一个长度为 10 的整数类型的数组,例如 [2, 10, 3, 4, 5, 11, 10, 11, 20],将其排列成一个新数组,要求新数组形式如下,例如 [[2, 3, 4, 5], [10, 11], [20]]。
// 我的理解是把连续的元素组成一个数组,例如1,2,3,4组成一个,9,10,11,12组成一个
// 随机生成数组
const randomAry = (n = 10, range = { min: 1, max: 20 }) => {
let ary = new Array(n).fill(0)
ary = ary.map((val) => {
val = Math.floor(Math.random() * (range.max - range.min + 1) + range.min)
return val
})
console.log('random: ', ary)
return ary
}
let ary = randomAry()
// 去重
ary = Array.from(new Set(ary))
// 排序
ary.sort((a, b) => a - b)
console.log('sorted: ', ary)
// 保存结果
let newAry = []
for (let i = 0; i < ary.length; i++) {
let tmpAry = [ary[i]]
// index用于跳过已经处理过的数组元素,为什么让初始值等于数组长度呢?因为内层循环执行最后一步时,index = j - 1这一条语句会被跳过,为了不出现死循环,所以让初始值等于数组长度
let index = ary.length
for (let j = i + 1, count = 1; j < ary.length; j++, count++) {
if (ary[i] + count === ary[j]) {
tmpAry.push(ary[j])
} else {
index = j - 1
break
}
}
i = index
// debugger
newAry.push(tmpAry)
}
console.log('result', newAry)
69题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 第 69 题: 如何把一个字符串的大小写取反(大写变小写小写变大写),例如 ’AbC' 变成 'aBc' 。
const reverseStr = (str) => {
let tmpAry = str.split('')
let resultAry = []
let a = 'a'.charCodeAt()
let A = 'A'.charCodeAt()
tmpAry.map((val) => {
// debugger
if (val <= 'Z' && val >= 'A') {
resultAry.push(String.fromCharCode(val.charCodeAt() + (a - A)))
} else if (val <= 'z' && val >= 'a') {
resultAry.push(String.fromCharCode(val.charCodeAt() - (a - A)))
} else {
resultAry.push(val)
}
})
return resultAry.join('')
}
console.log(reverseStr('aBCDefgh!@##%^$^*!@#$%'))
看到个大佬牛批的写法,用正则替换,贴一下。
1
2
3
'AbcDefGh'.replace(/[a-zA-Z]/g, function (a) {
return /[a-z]/.test(a) ? a.toUpperCase() : a.toLowerCase()
})
71题
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
// 第 71 题: 实现一个字符串匹配算法,从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置。
// 以下解法均只匹配第一次出现的子串,不考虑多次重复出现的情况。
// 暴力算法,不用api
const strMatch = (S, T) => {
let sLen = S.length, tLen = T.length
if (!sLen || !tLen || sLen < tLen) {
return -1
}
for (let i = 0; i < sLen - tLen + 1; i++) {
let tmp = i
let matched = true
for (let j = 0; j < tLen; j++) {
if (S[tmp] !== T[j]) {
matched = false
break
} else {
tmp++
}
}
if (matched) {
return i
}
}
return -1
}
console.log(strMatch('aaaaaaaaaaabcdfdfdfdfdfdf', 'aaaaaaaaaaa'))
// 经典的KMP解法,难,不写了。
// 调用JS各种库函数的解法
const matchIndexOf = (S, T) => {
return S.indexOf(T)
}
console.log(matchIndexOf('aaaaaaaaaaabcdfdfdfdfdfdf', 'aaaaaaaaaaa'));
const matchSearch = (S, T) => {
return S.search(T)
}
const matchSplit = (S, T) => {
let sLen = S.length, tLen = T.length
if (!sLen || !tLen || sLen < tLen) {
return -1
}
let ary = S.split(T)
if (ary.length > 1) {
return ary[0].length
}
}