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

前言

前几天固态直接挂了,幸亏桌面指向的E盘

C盘基本没东西,都放机械了。

现在换上新的固态终于能使用我最爱的电脑了,开心。

2020.08.23晚上参加了腾讯的前端笔试

先说说情况吧

5道题目

第一道字符串只有80通过

第二道最小区间(我觉得应该是考察的dp)40通过

第三道DOM题不会

第四道栈取最小值,100通过

第五道颜色格式判断题,没时间做了…

emmm,做了之后更加确认自己真的还是太嫩,还需要更加努力啊…

题目

因为我最后留了一点时间才截图的,没截图完全,只截图了第一道和第五道

其他几道没有截图下来,所以只能按照我口头的方式来将题目的要求了

解法就不用oj的输入输出的,直接用函数代替,然后再重新解一次

字符串截断

我的解法

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
function fn(str, n) {
let len = 0;
for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
// 英文1长度,中文2长度
if (c >= 0 && c <= 128) {
len++;
} else {
len += 2;
}
}

// 实际长度小于给定的长度,可以直接显示,直接返回
if (len <= n) {
return str;
}

let result = '';
let curLen = 0;

for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
if (c >= 0 && c <= 128) {
curLen++;
} else {
curLen += 2;
}
// 这里判断如果加上当前会超过 n-3的话(n减去3是因为要额外显示`...`)
if (curLen > n - 3) {
break;
}
// 拼接
result += str[i];
}
return result + '...';
}

找区间

题目不知道要怎么说

emmm,就是输入n,m,k和一个数组

其中n表示最后一个参数数组的长度,m表示需要的毫升数,k表示最低的平均温度,数组表示单位时间内的温度的数组

题目的要求就是从最后一个参数里面找到一段区间,这段区间的平均温度不小于k,区间长度不小于m,返回右边界

这里m<=n<=10^6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function fn(n, m, k, arr) {
if (n === 0) {
return -1;
}
const dp = [];
dp[0] = arr[0];
for (let i = 1; i < n; i++) {
dp[i] = dp[i - 1] + arr[i];
}
let right = 10000000;
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
let avg = (dp[j] - dp[i] + arr[i]) / (j - i + 1);
if (j - i + 1 >= m && avg >= k && j < right) {
right = j;
}
}
}
return right === 100000000 ? -1 : right;
}

这道题我确实没有什么思路,如果有思路的小伙伴可以联系我,一起学习哈哈哈哈

我上面这样做40通过率,错误的提示是样例超时,应该是最后那个二层循环的关系吧…

Excel表的Dom操作

通过实现一个bind函数,实现下面动图的效果

htmlcss题目已经提供了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="demo">
<table style="margin: 40px auto;">
<tbody>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
<tr><td class="wrap"></td><td class="wrap"></td><td class="wrap"></td><td class="current"></td><td class="wrap"></td><td class="wrap"></td></tr>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td class="wrap"></td><td></td><td></td></tr>
</tbody>
</table>
</div>
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
.wrap {
background-color: #efefef;
}
.current {
background-color: #4b8cff;
}
table {
border-spacing: 0;
}
table td {
width: 100px;
height: 30px;
border-left: 1px solid #c1c1c1;
}
table tr td:last-child {
border-right: 1px solid #c1c1c1;
}
table tr {
display: block;
}
table tr {
border-top: 1px solid #c1c1c1;
}
table tr:last-child {
border-bottom: 1px solid #c1c1c1;
}

需要实现的效果如下

题目我是不记得他怎么写的了,这些htmlcss我自己写的…

动图也是我自己做完录的…只能说当时自己傻逼,不把题目截图下来

不过问题应该不大,能还原题目的大概意思就行了

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
// 实现bind函数
function bind() {
// 得到tr的类数组
const row = document.getElementsByClassName("demo")[0]
.getElementsByTagName("tbody")[0].children;
// 得到td的数组,也就是整个棋盘。
const arr = Array.from(row).map(item => Array.from(item.children));
// 保存上一个点的坐标
let lastIndex = [-1, -1];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
// 这里是原题目html已经有一个点设置样式了
// 所以单独判断下是否存在已经设置过的点了
if (arr[i][j].className === 'current') {
lastIndex = [i, j];
}
// 绑定事件
arr[i][j].onclick = function () {
// 之前的点所影响的行列的样式要去掉
if (lastIndex[0] !== -1) {
for (let k = 0; k < arr[i].length; k++) {
arr[lastIndex[0]][k].className = '';
}
for (let k = 0; k < arr.length; k++) {
arr[k][lastIndex[1]].className = '';
}
}
// 设置当前点的样式
for (let k = 0; k < arr[i].length; k++) {
arr[i][k].className = 'wrap';
}
for (let k = 0; k < row.length; k++) {
arr[k][j].className = 'wrap';
}
arr[i][j].className = 'current';
// 更新上一个点的坐标
lastIndex = [i, j];
}
}
}
}

这道当时竟然没做出来,我真的是个🐕⑧傻逼

设计一个可以获取最小值的栈

这个我在LeetCode上做过了,所以很快就做出来了

贴下地址:剑指 Offer 30. 包含min函数的栈

思路上就是每次push的时候,不是直接往数组里面push

而是push一个对象,这个对象包含一个valmin属性

val记录值,min记录栈底到当前的最小值。

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
var MinStack = function () {
this.$$l = [];
};

MinStack.prototype.push = function (x) {
if (this.$$l.length === 0) {
this.$$l.push({
val: x,
min: x
});
} else {
this.$$l.push({
val: x,
min: Math.min(this.$$l[this.$$l.length - 1].min, x)
});
}
};

MinStack.prototype.pop = function () {
this.$$l.pop();
};

MinStack.prototype.top = function () {
return this.$$l[this.$$l.length - 1].val;
};

MinStack.prototype.min = function () {
return this.$$l[this.$$l.length - 1].min;
};

题目说过不会出现非法的操作,也就是比如空栈pop,空栈top,空栈min

所以不用在poptopmin进行判断是否在栈底

验证颜色是否合法

这题我最后不到10分钟才做到…

这题其实之后我也没啥好的思路,随便写了写

我的解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function isValidColor(colorStr) {
// 去空格
colorStr = colorStr.replace(/\s/g, '');
const hex = /^#[0-9a-f]{6}([0-9a-f]{2})?$/g;
const rgb = /^rgb\(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(,([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){2}\)$/g;
const rgba = /^rgba\(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(,([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){2},((0?(.[0-9][0-9]?)?)|1(.0{1,2}})?)\)$/g;
const hsl = /^hsl\(([0-9]|[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|360)(,([0-9]|[1-9][0-9]|100)%){2}\)$/g;
const hsla = /^hsla\(([0-9]|[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|360)(,([0-9]|[1-9][0-9]|100)%){2},((0?(.[0-9][0-9]?)?)|1(.0{1,2})?])\)$/g;
return hex.test(colorStr)
|| rgb.test(colorStr)
|| rgba.test(colorStr)
|| hsl.test(colorStr)
|| hsla.test(colorStr);
}

花了挺久时间的,测了一些特别的,都可以过,不过现在也没有可以测试完整的用例

如果发现了额外不通过的样例,可以联系我

alpha参数我是判断的小数点后最多两位的,三位报错…

我是看了百科对rgba中a的定义为1%到100%,所以就这样吧…

正则不是很会,高级的写法看了忘,忘了看…

后记

只能说这波和题目配合的不是很好

字符串题,dom题都是应该拿下的,哎

还是要多多磨练啊…