搜狐2021前端秋招笔试题笔记
考的时候实在很惨,考完后花了大半时间去总结。这里就说一下题目的大致内容和我的解题思路。当然代码是笔试完才写的,没有通过系统调试。
第一题:奖励兑换
小明现在有若干个A/B/C三类道具,现在可以将这三类道具兑换成奖励。规则如下:
- 一个A类、B类和C类道具可以兑换一次奖励。
- 道具不够时,可以拿其他两类道具共2个来兑换1个道具。例如1个A类道具和1个B类道具可以兑换1个C类道具,或者2个A类道具可以兑换1个C类道具。
现在请求出小明最多能兑换多少次奖励。
思路:
把三类道具的兑换分成三个阶段(假设数量 A >= B >= C)
- 一换一阶段:ABC道具都有,各一个兑换奖励。
- 二换一阶段:此时C道具以已经兑换完成,那么我们用A道具和B道具各一个来兑换C道具,AB各一个兑换C一个,然后ABC再兑换成奖励,因此此阶段兑换一次奖励需要2个A道具和2个B道具。
- 五换一阶段:此时B道具已经兑换完成,只剩A道具,那么兑换奖励需要2个A道具换成1个B道具,还需要2个A道具兑换成1个C道具,最后ABC各1个兑换奖励,因此此阶段需要5个A道具。
- 三换一阶段:这么兑换下去,ABC都换得差不多了,此时我们可以得到的信息是:A道具已经不足5个(5换1阶段中剩余的),B道具已经不足1个(2换1阶段中剩余的)。如果B道具还剩1个且A道具还剩3个以上,那么最后我们还可以用2个A道具兑换1个C道具,兑换最后一个奖励。
const changePrize = (a, b, c) => {
// 先把ABC道具按数量排序
let [la, lb, lc] = [a, b, c].sort((a, b) => b - a)
// 一换一阶段
let result = lc;
lb -= lc
la -= lc
// 二换一阶段
let count = lb >>> 1;
lb -= count * 2;
la -= count * 2;
result += count;
// 五换一阶段
count = Math.floor(la / 5);
la = la % 5;
result += count;
// 三换一阶段
if (la >= 3 && lb === 1) {
result++
}
return result
}
第二题:造房子
第二题当时做出来了(泪目)。
在一个1维的数轴上已经建造了若干个房子,它们的位置和面积分别是(xi, ai),也就是说,房子占的范围是[xi - ai / 2, xi + ai / 2]。
给定一个面积t,下面你要按照下面的规则盖一栋新房。
- 这个房子必须紧贴着其中一栋已经建好的房子。
- 没了,就这么多。
现在求有多少种建房子的方案。
思路:
- 最左边的房子可以建在它的左边,最右边的房子可以建在它的右边,因此已经有2种。
- 两栋房子的中间的情况,我们要判断他们之间的间隙gap是否能建面积为t的房子。
- gap < t 自然不能建房子。
- gap = t 只有一种建房子的方案。
- gap > t 有两种间房子的方案(贴着左边贴着右边都可以)。
第三题:高亮文本
给你一段html文本(例如是在id为content的容器内),现在给一个词word,要求高亮word及其子字符串:
- 为对应文本添加em标签,即
<em>word</em>
。- 高亮word的子字符串,即wor/wo/w。当然,已经高亮的字符串就不用再高亮了。
- 仅高亮第一次出现的字符串位置。
- html标签里面的文本不能高亮。例如若word为div,那么
<div>div</div>
高亮后应该<div><em>div</em></div>
。
思路:
- 可能可以用正则匹配替换(太难了写不出来)
- 用childNodes遍历,检查textNode的文本,发现第一个匹配项时,加上一些特殊标记。然后再替换。
// 搜狐笔试第三题
let test = (domArr, str) => {
for (let i = 0, len = domArr.length; i < len; i++) {
// 文本节点:判断文本内容
if (domArr[i].nodeType === 3) {
let index = domArr[i].data.indexOf(str)
if (index > -1) {
// 加一些特殊标记
domArr[i].data = domArr[i].data.replace(str, `[[${str}]]`)
let inner = document.getElementById('content').innerHTML
inner = inner.replace(`[[${str}]]`, `<em>${str}</em>`)
document.getElementById('content').innerHTML = inner
return true
}
}
// html元素节点,递归遍历其子节点,直到碰到文本节点
if (domArr[i].nodeType === 1) {
// 跳过高亮节点
if (domArr[i].tagName === "EM") {
continue
}
let res = test(domArr[i].childNodes, str)
if (res) return true
}
}
return false
}
/**
* 高亮搜索词
*/
const highlight = (word) => {
let inner = document.getElementById('content')
let children = inner.childNodes
for (let j = word.length; j > 0; j--) {
let str = word.substring(0, j)
test(children, str)
children = inner.childNodes
}
}