腾讯笔试,放水了(0331春招实习笔试真题解析)
- 2026-11-06 09:43:43
关注我们,每周更新两到三次大厂最新笔试题解析
前言
题目难度比较低。前面的题目主要是因为数据范围比较小,所以导致题目可以用一些比较暴力的方法来解,这也是难度不高的重要原因。最后一题的dp也是非常简单就可以解出来的。
腾讯的笔试在各个大厂里向来独具一格的,整个校招就那两天有笔试,甚至腾讯的笔试你不做,也不一定就拿不到offer,不过这次的笔试做起来有种充值了会员,降低了难度的感觉。
春招和暑期实习的笔试也陆陆续续开始啦,有参加笔试的同学欢迎投稿哦,投稿一场完整笔试的,有请你喝一周的奶茶的现金奖励!(投稿加文末微信,备注投稿)
文末也有我们的面向校招的一对一活动介绍,有兴趣参加活动也可以了解一下!
第一题 小红的链表节点删除
小红拿到了一个链表,她准备删除所有值恰好等于k的节点。你能帮帮她吗?
示例1
输入
{4,1,6,2,7,2}, 2
输出
{4,1,6,7}
思路与代码
非常简单,方法不唯一:下面的代码用一个哑节点来实现,更加简洁。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* deleteNode(ListNode* head, int k) {
ListNode dummy(-1), *p = &dummy;
while (head) {
if (head->val != k) {
p->next = head;
p = p->next;
}
head = head->next;
}
p->next = nullptr;
return dummy.next;
}
};
第二题 小红的二叉树路径权值
小红拿到了一棵二叉树,每个节点的权值为0或1。
小红希望从一个节点出发,每次前往左儿子或者右儿子,直到走到叶子时停止,路径上所有节点将表示为一个二进制数(按路径顺序)。小红希望最终的二进制数在区间[l,r]内,请你告诉小红有多少种不同方案。
二叉树的节点数量不超过
示例1
输入
{1,0,1,#,1},2,3
输出
1
说明

如上图所示,只有这—条路径合法。
思路与代码
比较简单,直接dfs即可,记住保存当前根节点到当前节点的二进制值,到叶子节点时,进行判断。
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param l int整型
* @param r int整型
* @return int整型
*/
int number_of_different_plans(TreeNode* root, int l, int r) {
int ans = 0;
auto dfs = [&](auto&& self, TreeNode* root, long x) {
if (!root) return;
x = x * 2 + root->val;
if (!root->left && !root->right) {
ans += (x >= l) and (x <= r);
}
if (x >= r) return;
self(self, root->left, x);
self(self, root->right, x);
};
dfs(dfs, root, 0);
return ans;
}
};
第三题 小红的路径统计
小红拿到了—棵树,她定义路径的权值为路径上所有节点的权值之和。小红想知道,有多少条权值为3的路径? 我们定义,u->v和v->u为同—条路径。
输入描述
第—行输入—个正整数n,代表节点的数量。
第二行输入n个正整数ai,代表每个节点的权值。
接下来的n ―1行,每行输入两个正整数u,v,代表节点u和节点v有一条路径连接。
输出描述
—个整数,代表权值为3的路径数量。
示例1
输入
3
1 2 1
1 2
2 3
输出
2
说明
有2个路径满足条件
路径1->2
路径2->3
思路与代码
其实感觉这一题还挺有意思的;可以用递归来解决,在子节点返回时,携带经过当前节点权值为1和2的路径树。在当前节点,保存子节点所有返回结果。如果当前节点为2,那么只有累加子节点路径为1的数目。如果节点为1,那么可以先累加子节点路径为1的数目,再加上左孩子节点路径为1与右孩子节点路径为1的情况,对于这一种情况,有些特殊,可以用组合统计的方法计算。
(这道题的范围太弱了,强行降低难度。。。)
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int main() {
int n; cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; ++i) cin >> a[i];
unordered_map<int, vector<int>> g;
for (int i = 0; i < n - 1; ++i) {
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
int ans = 0;
auto helper = [&](auto&& self, int i, int f) -> vector<int>{
vector<vector<int>> arr;
// one two
vector<int> sum(2, 0);
for (int nxt : g[i]) {
if (nxt == f) continue;
vector<int> v = self(self, nxt, i);
for (int j = 0; j < 2; ++j) sum[j] += v[j];
arr.push_back(v);
}
int m = arr.size();
if (a[i] == 2) {
ans += sum[0];
return {0, 1};
}
ans += sum[1];
int sum_0 = sum[0];
for (int i = 0; i < m - 1; ++i) {
sum[0] -= arr[i][0];
ans += arr[i][0] * sum[0];
}
return {1, sum_0};
};
helper(helper, 1, 0);
cout << ans;
}
第四题 小红的剪切线2.0
小红非常喜欢一首叫做剪切线的歌,所以小红现在非常喜欢剪切各种东西。
现在小红有—棵树,她需要剪切树上的一条边,将这棵树剪切成两棵树,小红想知道两棵树直径之差的绝对值的最小值是多少。
树的直径:树上任意两节点之间最长的简单路径即为树的直径。
输入描述
第—行输入—个整数n(1<n<1000)表示树的节点数。
接下来n一1行,每行输入两个正整数u, v(1 ≤u,v≤n)表示树上的边。
输出描述
输出—个整数表示答案。
示例1
输入
4
1 2
1 3
24
输出
0
说明
剪切边(1,2),剪切后两棵树的直径都为1,因此差值的绝对值为0。
思路与代码
注意数据的范围,只有1000个节点,所以可以枚举每条要剪切的边,然后再计算两棵树的直径。关于树的直径,可能需要额外注意下。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <unordered_set>
using namespace std;
int D = 0;
int main() {
int n; cin >> n;
unordered_map<int, unordered_set<int>> g;
for (int i = 0; i < n - 1; ++i) {
int u, v; cin >> u >> v;
g[u].emplace(v);
g[v].emplace(u);
}
auto dfs = [&](auto&& self, int i, int f) ->int {
vector<int> arr{0};
bool leaf = true;
for (int nxt : g[i]) {
if (nxt == f) continue;
int a = self(self, nxt, i);
arr.push_back(a);
leaf = false;
}
if (leaf) {
D = max(D, 1);
return 1;
}
sort(arr.begin(), arr.end(), greater<>());
D = max(D, arr[0] + arr[1] + 1);
return arr[0] + 1;
};
int ans = 0x3f3f3f3f;
auto helper = [&](auto&& self, int i, int f) -> void{
auto st = g[i];
for (int nxt : st) {
if (nxt == f) continue;
// 剪切这一条边
g[i].erase(nxt); g[nxt].erase(i);
int a = 0, b = 0;
D = 0; dfs(dfs, 1, 0); a = D;
D = 0; dfs(dfs, nxt, 0); b = D;
// cout << i << " " << nxt << " " << a << " " << b << "\n";
ans = min(ans, abs(a - b));
// 重连
g[i].emplace(nxt); g[nxt].emplace(i);
self(self, nxt, i);
}
};
helper(helper, 1, 0);
cout << ans;
}
第五题 小红小紫寻宝
有一个大小为n × m的地图,地图上每个格子都是红色或紫色的,每个格子都有一个价值为aj的宝藏,小红只能挖红色格子上的宝藏,小紫只能挖紫色格子上的宝藏。
小红和小紫初始在地图左上角,她们只能同时向下或向右走,她们挖宝有以下限制: 1.有的格子可以跳过不挖。2.对于同一个人,不能连续挖两个相邻的格子。
她们想知道走到地图右下角—共能获得的宝藏的最大价值和是多少。
输入描述第—行输入两个整数n, m() . 接下来n行,每行输入m个整数agq(1≤aj ≤109)表示地图上每个点的价值。接下来n行,每行输入一个长度为'm的只由'R'和'P'组成的字符串表示地图每个格子的颜色,'R'代表格子为红色,'P'代表格子为紫色。
输出描述
输出—个整数。
示例1
输入
3 3
321
333
123
RPR
PRP
RPR
输出
15
说明
第0步,小红挖(1,1)格子,获得价值为3的宝藏。第1步,小红和小紫往下走,小紫挖(2,1)格子,获得价值为3的宝藏。第2步,小红和小紫往右走,小红挖(2,2)格子,获得价值为3的宝藏。第3步,小红和小紫往右走,小紫挖(2,3)格子,获得价值为3的宝藏。第4步,小红和小紫往下走,小红挖(3,3)格子,获得价值为3的宝藏。总共获得了价值为3+3+3+3+3=15的宝藏。
思路与代码
非常典型的动态规划,每个位置只有两种状态,不挖和挖;此外,题目有限制,“对于同一个人,不能连续挖两个相邻的格子”,因此可再加一个状态,表示当前位置向哪里转移(在下一步可以判断除是否连续挖两个相邻的格子);之后可以记忆化递归直接秒了。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <unordered_set>
#include <string>
#include <cstring>
using namespace std;
using ll = long long;
ll memo[1001][1001][3];
int main() {
int n, m; cin >> n >> m;
vector<vector<int>> g(n, vector<int>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> g[i][j];
}
}
vector<string> c(n);
for (int i = 0; i < n; ++i) cin >> c[i];
// op: 0 没挖, 1上挖, 2左挖
auto helper = [&](auto&& self, int i, int j, int op) ->ll {
if (i >= n || j >= m) return 0;
if (memo[i][j][op] != -1) return memo[i][j][op];
// 不挖
ll a = max(self(self, i + 1, j, 0), self(self, i, j + 1, 0));
// 挖
ll b = -1e9;
bool ok = false;
if (op == 0) ok = true;
else if (op == 1) ok = c[i-1][j] != c[i][j];
else ok = c[i][j-1] != c[i][j];
if (ok) {
b = max(self(self, i + 1, j, 1), self(self, i, j + 1, 2)) + g[i][j];
}
return memo[i][j][op] = max({a, b, 0LL});
};
memset(memo, -1, sizeof(memo));
cout << helper(helper, 0, 0, 0);
}
最后插一下我们的进阶一对一辅导啦
我们是一个针对技术岗(前后端开发、测试、测开、大数据开发)校招一对一进阶提高的工作室。我们从2020年2月份开始,迄今整整三年的时间,带领300+学员斩获1500+大厂offer,参加活动的同学人均5个中大厂offer以上,以下是我们活动内容的介绍! 万诺coding
我们主要是针对有一定基础的同学提供一对一面试辅导,针对每个同学不同的情况定制内容,包括但不限于“数据结构与算法”/“计算机基础知识”/“项目梳理”/“面试技巧”/“面试复盘”等内容。
摸底测试:如果有兴趣深入了解我们的活动,需要先参加我们的“摸底测试”(类似面试),方便我们了解你的具体情况(主要是code能力和计算机素养),定制出相应的辅导计划。同时这也是一个双向筛选的过程,如果基础过差的同学,抱歉我们可能无法辅导(基础过差的同学一对一辅导成本过高,对双方都不适合);摸底测试通过的同学,我们会定制化一个针对性的提高计划。然后你再考虑是否参加我们的活动。
承诺保offer:通过摸底测试后,我们会针对每个同学的情况给定一个“保offer”计划。然后同学可以根据自己的实际情况考虑参不参加我们的活动。
有兴趣的同学可以扫码添加我们的微信(whynotlab)