10.16 字节笔试编程题题解
国庆前做过一次字节笔试,没约我面试。十天后又给我发了个国庆结束的笔试,我没做,前几天又给我发了这场的笔试。真是服了,不知道字节在搞什么鬼。
做的两次都AK了。
// 老规矩,笔试时间结束发题解。
1. 某游戏,每一局需要多个玩家参与。若发现有两玩家同时参与过至少两局游戏,即认为这两个玩家互为队友。
现已知若干玩家(玩家id, int)、若干局游戏(游戏id, int)的历史记录,求某一个指定玩家的所有队友。
第0行输入指定玩家。
第1行输入玩家/游戏记录条数: n (0 <n < 1000000)。
第2 - n+2行输入玩家游戏记录,格式为“玩家id 游戏id”。两个id中间用空格分隔,id 取值范围均为1-10000000。
德州扑克不包含大小王,一共13*4=52张牌,其中A > K > Q > J > 10 > ... > 2。
给你一组牌,让你从其中选出最大的葫芦。
输入一组取值范围为1-13的数,1代表A,11代表J,12代表Q,13代表K
输出最大的牌型,如果找不到输出0,0
数组长度 <= 300,值 <= 1e9。
初始状态给出每个文件夹内部所拥有的文件夹。然后给出一些剪切操作:形如move a b,指将a文件夹移动到b文件夹下(从原所属文件夹中删除)。
题目保证,b文件夹—定不是a文件夹的一个子集。
特殊的,如果b字符串为".",则代表移动至根目录下。
当所有操作结束后,你需要输出每个文件夹内部的文件夹数量,按文件夹名字字典序排序输出。
输入描述:
第一行输入一个正整数n,代表空文件夹的数量
接下来的n行,每行输入一个字符串,代表每个空文件夹的绝对路径。第n+1行,输入一个正整数q,代表操作次数。
接下来的q行,每行输入一个形如"move a b"的字符串,代表一次剪切操作。
保证每个文件夹的名字都是长度不超过10的、仅由小写字母组成的字符串。每个文件夹的名字是独一无二的。
保证所有输入的形式都是合法的。
剪切操作保证b文件夹一定不是a文件夹内部的子文件夹。所有文件夹数量不超过10000,操作次数不超过10000。
输出描述:
第一行输出一个正整数m,代表文件夹的总数。
接下来的m行,每行输出一个字符串和一个整数,代表文件夹的名字和其内部文件夹的数量。请保证文件夹的输出顺序是按照名字字典序排序的。
请保证文件夹的输出顺序是按照名字字典序排序的。
#字节跳动笔试##字节笔试#现已知若干玩家(玩家id, int)、若干局游戏(游戏id, int)的历史记录,求某一个指定玩家的所有队友。
第0行输入指定玩家。
第1行输入玩家/游戏记录条数: n (0 <n < 1000000)。
第2 - n+2行输入玩家游戏记录,格式为“玩家id 游戏id”。两个id中间用空格分隔,id 取值范围均为1-10000000。
#include <bits/stdc++.h> using namespace std; int main() { int x; cin >> x; int n; cin >> n; // 记录每个人都参加了哪些游戏 unordered_map<int, set<int>> pls; // players int a, b; for (int i = 0; i < n; i++) { cin >> a >> b; pls[a].insert(b); } set<int> ans; for (auto &p : pls) { if (p.first == x) continue; auto it1 = pls[x].begin(), it2 = p.second.begin(); int cnt = 0; while (it1 != pls[x].end() && it2 != p.second.end()) { if (*it1 < *it2) it1 ++; else if (*it1 > *it2) it2 ++; else { it1 ++; it2 ++; if (++ cnt == 2) { break; } } } if (cnt == 2) { ans.insert(p.first); } } for (auto a : ans) { printf("%d ", a); } return 0; }2. 德州扑克里面有一种牌型叫做葫芦,该牌型由5张牌组成,包含3张相同的牌a和两张相同的牌b。
德州扑克不包含大小王,一共13*4=52张牌,其中A > K > Q > J > 10 > ... > 2。
给你一组牌,让你从其中选出最大的葫芦。
输入一组取值范围为1-13的数,1代表A,11代表J,12代表Q,13代表K
输出最大的牌型,如果找不到输出0,0
#include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; vector<int> v(n); for (int i = 0; i < n; i++) cin >> v[i]; vector<int> cnt(14); for (int x: v) cnt[x] ++; // a 记录牌数超过 3 张的面值,b 记录牌数为 2 的面值。 // 答案要不都从 a 中取,要不从 a 和 b 中取 vector<int> a, b; for (int i = 1; i <= 13; i++) { if (cnt[i] >= 3) a.push_back(i); else if (cnt[i] == 2) b.push_back(i); } // 因为 A > K > Q > J > 10 > .... > 2,将 A 映射成 14 即可直接比较 auto toVal = [] (int x) -> int { return x == 1 ? 14 : x; }; // 比较 3张a1 2张a2 和 3张b1 2张b2 哪个牌型大 auto cmp = [&] (int a1, int a2, int b1, int b2) -> bool { return toVal(a1) > toVal(b1) || (toVal(a1) == toVal(b1) && toVal(a2) > toVal(b2)); }; int ans1 = 0, ans2 = 0; for (auto x: a) { for (auto y: a) { if (x == y) continue; if (x*3 + y*2 <= m) { if (!ans1 || cmp(x, y, ans1, ans2)) { ans1 = x; ans2 = y; } } } for (auto y: b) { if (x*3 + y*2 <= m) { if (!ans1 || cmp(x, y, ans1, ans2)) { ans1 = x; ans2 = y; } } } } cout << ans1 << " " << ans2 << endl; return 0; }3. 给你一个整数数组,求能从该数组中选出的最长等差数列的长度。
数组长度 <= 300,值 <= 1e9。
#include <bits/stdc++.h> using namespace std; // 动态规划 int main() { int n; cin >> n; vector<int> v(n); for (int i = 0; i < n; i++) cin >> v[i]; sort(v.begin(), v.end()); vector<vector<int>> f(n, vector<int>(n, 2)); for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { for (int k = j+1; k < n; k++) { if (v[k] - v[j] == v[j] - v[i]) { f[j][k] = max(f[j][k], f[i][j]+1); } } } } int ans = 1; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) continue; ans = max(ans, f[i][j]); } } cout << ans << endl; return 0; }4. 请你实现—个文件移动系统,进行如下操作:
初始状态给出每个文件夹内部所拥有的文件夹。然后给出一些剪切操作:形如move a b,指将a文件夹移动到b文件夹下(从原所属文件夹中删除)。
题目保证,b文件夹—定不是a文件夹的一个子集。
特殊的,如果b字符串为".",则代表移动至根目录下。
当所有操作结束后,你需要输出每个文件夹内部的文件夹数量,按文件夹名字字典序排序输出。
输入描述:
第一行输入一个正整数n,代表空文件夹的数量
接下来的n行,每行输入一个字符串,代表每个空文件夹的绝对路径。第n+1行,输入一个正整数q,代表操作次数。
接下来的q行,每行输入一个形如"move a b"的字符串,代表一次剪切操作。
保证每个文件夹的名字都是长度不超过10的、仅由小写字母组成的字符串。每个文件夹的名字是独一无二的。
保证所有输入的形式都是合法的。
剪切操作保证b文件夹一定不是a文件夹内部的子文件夹。所有文件夹数量不超过10000,操作次数不超过10000。
输出描述:
第一行输出一个正整数m,代表文件夹的总数。
接下来的m行,每行输出一个字符串和一个整数,代表文件夹的名字和其内部文件夹的数量。请保证文件夹的输出顺序是按照名字字典序排序的。
请保证文件夹的输出顺序是按照名字字典序排序的。
#include <bits/stdc++.h> using namespace std; struct TreeNode { string name; TreeNode *fa; unordered_set<TreeNode*> son; TreeNode(string s): name(s), fa(nullptr) {} TreeNode(string s, TreeNode *fa): name(s), fa(fa) {} void addSon(TreeNode *node) { son.insert(node); node->fa->son.erase(node); node->fa = this; } }; map<string, int> ans; int calSon(TreeNode *root) { int total = root->son.size(); for (auto s: root->son) { total += calSon(s); } ans[root->name] = total; return total; } int main() { int n; cin >> n; string s, t, pre; unordered_map<string, TreeNode*> mp; for (int i = 0; i < n; i++) { cin >> s; t.clear(); pre.clear(); for (int j = 0, jend = s.length(); j <= jend; j ++) { if (j == jend || s[j] == '/') { if (!mp.count(t)) { mp[t] = new TreeNode(t, pre.empty() ? nullptr : mp[pre]); if (!pre.empty()) { mp[pre]->son.insert(mp[t]); } } pre = t; t.clear(); } else { t += s[j]; } } } int q; cin >> q; string a, b, _; while (q --) { cin >> _ >> a >> b; mp[b]->addSon(mp[a]); } _ = calSon(mp["."]); cout << ans.size()-1 << endl; for (auto &p : ans) { if (p.first == ".") continue; cout << p.first << " " << p.second << endl; } return 0; }