1. 筛选出现频次最高的JS对象
一个一维数组内有多个对象,且对象可重复出现,要求写一个函数,返回出现频次最高的对象列表。
const obj1 = {};
const obj2 = {};
const arr = [obj1, obj2, obj1, obj1];
function find(arr) {
const result = [];
// ...
return result;
}
console.log(find(arr));
看见这道题我的解题思路就是找到数组中的众数,所以我想到的就是统计数组中每个元素出现的次数并记录下来。
const obj1 = { a: 1 }
const obj2 = { a: 2 }
const obj3 = { a: 3 }
const arr = [obj1, obj1, obj1, obj3, obj2]
function find(arr) {
let result = []
const countArr = [] // 计数用数组
const keyArr = [] // 去重后的数组,与上面的计数数组下标一一对应
let max = 0 // 用来储存最大值
// 这次循环将每个元素的出现次数统计出来了
arr.forEach(item => {
if (keyArr.includes(item)) {
countArr[keyArr.indexOf(item)]++
} else {
countArr.push(1)
keyArr.push(item)
}
})
// 这次循环则是找到出现次数最多的元素,然后push进结果数组输出
countArr.forEach((item, index) => {
if (item > max) {
max = item
result = [keyArr[index]] // 有更大的值,替换之前的结果
} else if (item === max) {
result.push(keyArr[index])
}
})
return result
}
console.log(find(arr))
上面是我当时写的代码,面试结束后我一直在想自己使用了两次循环感觉还存在优化空间,能不能一次循环就搞定呢?答案是能,下面是我优化后的代码
const obj1 = { a: 1 }
const obj2 = { a: 2 }
const obj3 = { a: 3 }
const arr = [obj1, obj1, obj1, obj3, obj2]
function find(arr) {
let result = []
const countArr = [] // 计数用数组
const keyArr = [] // 去重后的数组,与上面的计数数组下标一一对应
let max = 0 // 用来储存最大值
// 这里都优化在于我在统计元素出现次数的时候就开始寻找最大值了,把寻找最大值的那次循环合并的这次循环里
arr.forEach(item => {
if (keyArr.includes(item)) {
const keyArrIndex = keyArr.indexOf(item)
const countNum = ++countArr[keyArrIndex]
if (countNum > max) {
max = countNum
result = [keyArr[keyArrIndex]] // 有更大的值,替换之前的结果
} else if (countNum === max){
result.push(keyArr[keyArrIndex])
}
} else {
countArr.push(1)
keyArr.push(item)
}
})
return result
}
console.log(find(arr))
2. JS对象等概率乱排
对一个数组(长度>=3)进行乱序排序,要求每个元素不会落到原来的位置,且落到其他位置的概率相同
const obj1 = {};
const obj2 = {};
const obj3 = {};
const arr = [obj1, obj2, obj3];
function sort(arr) {
// ...
return arr;
}
console.log(sort(arr));
看到这道题我想到的是用洗牌算法:
先从数组末尾开始,选取最后一个元素,与数组中最后一个元素以外随机一个元素交换位置。然后再选取数组倒数第二个元素,与数组的后两个元素以外随机一个元素换位置,以此类推。这个方法就像洗牌一样将上面的牌随机插入牌堆中间。
const obj1 = { a: 1 }
const obj2 = { a: 2 }
const obj3 = { a: 3 }
const obj4 = { a: 4 }
const obj5 = { a: 5 }
const arr = [obj1, obj2, obj3, obj4, obj5]
function sort(arr) {
let result = JSON.parse(JSON.stringify(arr))
for (let i = arr.length - 1; i > 0 ; i--) {
const random = Math.floor(Math.random() * i)
const save = result[random]
result.splice(random, 1, result[i])
result.splice(i, 1, save)
}
return result
}
console.log(sort(arr))
使用es6的写法可以让代码更简洁
const obj1 = { a: 1 }
const obj2 = { a: 2 }
const obj3 = { a: 3 }
const obj4 = { a: 4 }
const obj5 = { a: 5 }
const arr = [obj1, obj2, obj3, obj4, obj5]
function sort(arr) {
let result = JSON.parse(JSON.stringify(arr))
for (let i = arr.length - 1; i > 0 ; i--) {
const random = Math.random() * i >>> 0; // 二进制无符号右移运算
[result[i], result[random]] = [result[random], result[i]] // 解构赋值
}
return result
}
console.log(sort(arr))