恋の歌的logo
Auto
归档 标签

2021腾讯校招前端第二次笔试题总结

发表于2020-09-07 10:14
更新于2023-02-13 18:28
分类于笔试
总字数2.3K
阅读时长 ≈8 分钟

2021腾讯校招前端第二次笔试题总结

两个有序的数组合并成一个 🔗

这题就是我上面说的能 ac100%,但是因为粗心只 ac 了 60%…。

原因就是腾讯的笔试题都是采用的标准输入输出。

所有的输入数据都要手动的处理成我们想要的样子。

V8 的输入输出就是readline(读取一行)和print(打印一行)。

这题给的样例输入输出如下(没记错应该是这个样例)。

text
输入:
1,2,4
1,3,4

输出:
1,1,2,3,4,4

也就是读取两行,转成数组再操作。

可是我傻逼了,用了split(',')之后忘记转成数字了…

这就导致了算法没错,但是比较的结果出错了。

javascript
"3" > "122"; // true
3 > 122; // false

整体的算法如下(这个就是归并排序中每一次合并的一个算法)。

这题应该考察双指针的知识点吧。

javascript
function merge(arr1, arr2) {
  let i = 0;
  let j = 0;
  let k = 0;
  const result = [];
  while (i < arr1.length && j < arr2.length) {
    if (arr1[i] < arr2[j]) {
      result.push(arr1[i]);
      i++;
    } else {
      result.push(arr2[j]);
      j++;
    }
    k++;
  }

  // 这里防止两个数组有一个没遍历完成,要直接把剩下的元素push的结果集的末尾
  if (i < arr1.length) {
    for (k = i; k < arr1.length; k++) {
      result.push(arr1[k]);
    }
  } else {
    for (k = j; k < arr2.length; k++) {
      result.push(arr2[k]);
    }
  }

  return result;
}

const arr1 = readline()
  .split(",")
  .map((s) => Number.parseInt(s));
const arr2 = readline()
  .split(",")
  .map((s) => Number.parseInt(s));

const result = merge(arr1, arr2);

print(result.join(","));

写到中间想起来没转成数字这件事,写着写着又给忘了…

JSON的扁平化 🔗

题意大致就是有一个对象,每秒会记录当时的点击量。

要求给你一个这个对象的json格式,转成数组形式。

text
输入:
{ "1": 123, "2": 234, "8": 7 }

输出:
[123, 234, 0, 0, 0, 0, 0, 7]

这题很快就ac了还是相当开心的。

javascript
function fn(str) {
  const obj = JSON.parse(str);

  const result = [];

  // 得到所有的key,也就是所有的秒数
  Object.keys(obj).forEach((item) => {
    const i = Number.parseInt(item);
    if (i > 0 && i <= Number.MAX_SAFE_INTEGER) {
      // 索引为秒数 - 1
      result[i - 1] = obj[i];
    }
  });

  for (let i = 0; i < result.length; i++) {
    // 找空位,以0代替
    if (result[i] === undefined) {
      result[i] = 0;
    }
  }

  return result;
}

const str = readline();
const result = fn(str);
// json形式输出
print("[" + result.join(",") + "]");

计算中位数 🔗

给定一个长度为nn 为偶数)的数组,问如果删除每一位之后,剩下的n - 1位的数组中位数是多少。

text
输入:
6
1 2 3 4 5 6

输出
4       // 删除1之后,剩下的数组中位数为4
4       // 删除2之后,剩下的数组中位数为4
4       // 删除3之后,剩下的数组中位数为4
3       // 删除4之后,剩下的数组中位数为3
3       // 删除5之后,剩下的数组中位数为3
3       // 删除6之后,剩下的数组中位数为3

这题我觉得我思路应该是没错的。

思路就是我们要先保存原来的索引,然后对这个数组进行排序。

由于数组的长度是偶数,我们可以知道。

如果删除了前 n / 2 个数中的某一个,那么中位数一定是第 n / 2 + 1 个。

如果删除了后 n / 2 个数中的某一个,那么中位数一定是第 n / 2 个。

可以以他的样例1 2 3 4 5 6

如果删除了3前面的任意一个数,包括3,那么中位数就会落到4这个数字上。

  • 2 3 4 5 6
  • 1 3 4 5 6
  • 1 2 4 5 6

如果删除了4后面的任意一个数,包括4,那么中位数就会落到3这个数字上。

  • 1 2 3 5 6
  • 1 2 3 4 6
  • 1 2 3 4 5

理解上面之后就可以写代码了。

javascript
function fn(n, arr) {
  // 保存每个数字原来位置的索引
  // 这里要注意原题目并没有说数组不重复,所以存一个索引数组
  const map = {};
  for (let i = 0; i < arr.length; i++) {
    if (map[arr[i]] === undefined) {
      map[arr[i]] = [i];
    } else {
      map[arr[i]].push(i);
    }
  }

  // 排序,开始求中位数
  arr.sort();
  // 右中位数的索引
  const rightMid = n / 2;
  // 左中位数的索引
  const leftMid = rightMid - 1;
  // 两者对应的值
  const rightMidVal = arr[rightMid];
  const leftMidVal = arr[leftMid];

  const result = [];
  // 删除[0, leftMid]索引中的其中一个值,剩下的中位数一定是rightMidVal
  for (let j = 0; j <= leftMid; j++) {
    // 得到这个数原来对应的索引位置
    const indexArr = map[arr[j]];
    // 写入结果集
    for (let i = 0; i < indexArr.length; i++) {
      result[indexArr[i]] = rightMidVal;
    }
  }
  // 删除[rightMid, arr.length)索引中的其中一个值,剩下的中位数一定是leftMidVal
  for (let j = rightMid; j < arr.length; j++) {
    // 跟上面同理
    const indexArr = map[arr[j]];
    for (let i = 0; i < indexArr.length; i++) {
      result[indexArr[i]] = leftMidVal;
    }
  }

  return result;
}

// 输入
const n = Number.parseInt(readline());
const arr = readline()
  .split(" ")
  .map((s) => Number.parseInt(s));

const result = fn(n, arr);
// 输出
result.forEach((val) => print(val));

写的时候紧张了,这题也应该拿下的。

Dom题:实现一个日期的组件 🔗

这个确实做不出来… 因为对日期的API不是特别的熟悉。

html代码如下:

html
<div id="js-container">
  <div class="calendar">
    <table>
      <thead>
        <tr>
          <th class="pre"></th>
          <th colspan="5" class="date">2020.01</th>
          <th class="next"></th>
        </tr>
        <tr>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td></td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
          <td>6</td>
        </tr>
        <tr>
          <td>7</td>
          <td>8</td>
          <td>9</td>
          <td>10</td>
          <td>11</td>
          <td>12</td>
          <td>13</td>
        </tr>
        <tr>
          <td>14</td>
          <td>15</td>
          <td>16</td>
          <td>17</td>
          <td>18</td>
          <td>19</td>
          <td>20</td>
        </tr>
        <tr>
          <td>21</td>
          <td>22</td>
          <td>23</td>
          <td>24</td>
          <td>25</td>
          <td>26</td>
          <td>27</td>
        </tr>
        <tr>
          <td>28</td>
          <td>29</td>
          <td>30</td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

css样式:

css
.current {
  background-color: #4b8cff;
  color: white;
}

#js-container {
  display: flex;
  justify-content: center;
  margin-top: 30px;
}

table {
  border-spacing: 0;
  border-collapse: collapse;
}

table td,
table th {
  width: 100px;
  height: 40px;
  border-left: 1px solid #c1c1c1;
  text-align: center;
}

table tr td:last-child,
table tr th:last-child {
  border-right: 1px solid #c1c1c1;
}

table tr {
  border-top: 1px solid #c1c1c1;
}

table tr:last-child {
  border-bottom: 1px solid #c1c1c1;
}

js如下:

javascript
function Calendar(year, month) {
  this.month = month;
  this.year = year;
  this.el = null; // TODO 挂载元素
  if (!this.el) {
    return;
  }
  this.el.addEventListener("click", (event) => {
    const target = event.target;
    const isPre = target.classList.contains("pre");
    const isNext = target.classList.contains("next");
    if (!isPre && !isNext) {
      return;
    }
    // TODO 更新month和year
    this.el.innerHTML = this.innerHTML();
  });

  this.innerHTML = function () {
    const year = +this.year || 0;
    const month = (+this.month || 0) - 1;
    const date = new Date();
    // TODO 生成html字符串
    return "";
  };
}

这题就要我们填充三个TODO

前两个TODO还好, 比较简单,难度在第三个TODO

javascript
function Calendar(year, month) {
  this.month = month;
  this.year = year;
  this.el = document
    .getElementById("js-container")
    .getElementsByClassName("calendar")[0]
    .getElementsByTagName("table")[0];
  if (!this.el) {
    return;
  }
  this.el.addEventListener("click", (event) => {
    const target = event.target;
    const isPre = target.classList.contains("pre");
    const isNext = target.classList.contains("next");
    if (!isPre && !isNext) {
      return;
    }
    if (isPre) {
      // 点击了上一个月
      if (this.month === 1) {
        this.year--;
        this.month = 12;
      } else {
        this.month--;
      }
    } else if (isNext) {
      // 点击了下一个月
      if (this.month === 12) {
        this.year++;
        this.month = 1;
      } else {
        this.month++;
      }
    }
    this.el.innerHTML = this.innerHTML();
  });

  this.innerHTML = function () {
    const year = +this.year || 0;
    const month = (+this.month || 0) - 1;
    const cur = new Date(); // 当前时间

    let xq = new Date(year, month, 1).getDay();
    // 因为getDay中星期天返回的是0,我们需要把他设置为索引第6位,同时星期1到6设置成对应0-5的索引
    // 我们只会获取第一天,因为完成整个日期数组并不会需要用到这个getDay()的API
    // 我们只需要第一天正确的在数组里面的位置即可
    xq = xq === 0 ? 6 : xq - 1;
    // 获取这个月有多少天,这里设置为天数设置为0的意思是,获取上一个月的最后一天是这个月中的第几天
    // 所以我们其实是获取了下一个月(month + 1)的上一个月(month)的最后一天处于那个月的第几天
    // 而第几天也就意味着这个月有多少天(范围 1 - 31)
    const day = new Date(year, month + 1, 0).getDate();
    const r = [];

    for (let i = 0; i < day; i++) {
      const j = i + xq;
      const row = Math.floor(j / 7);
      const col = j % 7;
      if (r[row] === undefined) {
        r[row] = [];
      }
      // 如果正好是这个月的当天,就把对应的天数设置成负数
      if (
        cur.getDate() === i + 1 &&
        cur.getMonth() === month &&
        cur.getFullYear() === year
      ) {
        r[row][col] = -(i + 1);
      } else {
        r[row][col] = i + 1;
      }
    }

    let trs = "";
    for (let i = 0; i < r.length; i++) {
      let tds = "";
      for (let j = 0; j < 7; j++) {
        if (r[i][j] !== undefined) {
          // 负数设置当天的样式
          if (r[i][j] < 0) {
            tds += `<td class="current">${-r[i][j]}</td>`;
          } else {
            tds += `<td>${r[i][j]}</td>`;
          }
        } else {
          tds += `<td></td>`;
        }
      }
      trs += `<tr>${tds}</tr>`;
    }

    return `<thead>
              <tr>
                <th class="pre"><</th>
                <th colspan="5" class="date">
                  ${this.year}
                  .
                  ${this.month < 10 ? "0" + this.month : this.month}
                </th>
                <th class="next">></th></tr>
              <tr>
                <th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th><th>日</th>
              </tr>
          </thead>
          <tbody>
            ${trs}
          </tbody>`;
  };
  // new的时候第一次初始化
  this.el.innerHTML = this.innerHTML();
}

new Calendar(2020, 9);

写半个多小时,写出来的,期间看了MDN上的API

昨晚考完就断断续续的想了,今天再写就不会特别的慢。

感觉非常棒的一道题。

放个运行的图:

消消乐(栈题) 🔗

写这题剩 10 分钟,还没写完系统就交卷了…

给定n个字符串,如果有两个相同的字符挨在一起,就把它们消去,消去之后的字符串如果符合规则也要继续消去,输出需要消去的次数

text
输入:
2
abcddcba
101

输出:
4       // 消去了dd,cc相碰消去,bb相碰消去,aa相碰消去,共消去4此
0       // 无法消去

这题我刚看到就觉得是考察栈的知识点的。

javascript
function fn(n, arr) {
  const result = [];
  for (let i = 0; i < n; i++) {
    if (arr[i].length === 0 || arr[i].length === 1) {
      result.push(0);
      continue;
    }
    const strArr = arr[i].split("");
    const stack = [];
    stack[0] = strArr[0];
    let j = 1;
    let count = 0;
    while (j < strArr.length) {
      const peek = stack[stack.length - 1];
      if (peek === strArr[j]) {
        // 消去
        count++;
        stack.length--;
      } else {
        // push进数组
        stack[stack.length] = strArr[j];
      }
      j++;
    }
    result.push(count);
  }
  return result;
}

const n = Number.parseInt(readline());
const arr = [];
for (let i = 0; i < n; i++) {
  arr.push(readline());
}

const result = fn(n, arr);
result.forEach((val) => print(val));
#JavaScript
#前端笔试题
哦呐该,如果没有评论的话,瓦达西...