搜狐2021前端秋招笔试题后记

搜狐2021前端秋招笔试题笔记

考的时候实在很惨,考完后花了大半时间去总结。这里就说一下题目的大致内容和我的解题思路。当然代码是笔试完才写的,没有通过系统调试。

第一题:奖励兑换
小明现在有若干个A/B/C三类道具,现在可以将这三类道具兑换成奖励。规则如下:

  1. 一个A类、B类和C类道具可以兑换一次奖励。
  2. 道具不够时,可以拿其他两类道具共2个来兑换1个道具。例如1个A类道具和1个B类道具可以兑换1个C类道具,或者2个A类道具可以兑换1个C类道具。

现在请求出小明最多能兑换多少次奖励。
思路:

把三类道具的兑换分成三个阶段(假设数量 A >= B >= C)

  1. 一换一阶段:ABC道具都有,各一个兑换奖励。
  2. 二换一阶段:此时C道具以已经兑换完成,那么我们用A道具和B道具各一个来兑换C道具,AB各一个兑换C一个,然后ABC再兑换成奖励,因此此阶段兑换一次奖励需要2个A道具和2个B道具。
  3. 五换一阶段:此时B道具已经兑换完成,只剩A道具,那么兑换奖励需要2个A道具换成1个B道具,还需要2个A道具兑换成1个C道具,最后ABC各1个兑换奖励,因此此阶段需要5个A道具。
  4. 三换一阶段:这么兑换下去,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,下面你要按照下面的规则盖一栋新房。

  1. 这个房子必须紧贴着其中一栋已经建好的房子。
  2. 没了,就这么多。

现在求有多少种建房子的方案。
思路:

  1. 最左边的房子可以建在它的左边,最右边的房子可以建在它的右边,因此已经有2种。
  2. 两栋房子的中间的情况,我们要判断他们之间的间隙gap是否能建面积为t的房子。
  • gap < t 自然不能建房子。
  • gap = t 只有一种建房子的方案。
  • gap > t 有两种间房子的方案(贴着左边贴着右边都可以)。

第三题:高亮文本
给你一段html文本(例如是在id为content的容器内),现在给一个词word,要求高亮word及其子字符串:

  1. 为对应文本添加em标签,即<em>word</em>
  2. 高亮word的子字符串,即wor/wo/w。当然,已经高亮的字符串就不用再高亮了。
  3. 仅高亮第一次出现的字符串位置。
  4. html标签里面的文本不能高亮。例如若word为div,那么<div>div</div>高亮后应该<div><em>div</em></div>

思路:

  1. 可能可以用正则匹配替换(太难了写不出来)
  2. 用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
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值