字节2020笔试题总结
第一题:
这种字符串模式匹配的题经常采用有限状态机的方法,差一点的方法是双指针,一般会更加麻烦,要熟悉状态机的使用。
我的代码:
#include<string> #include<vector> #include<iostream> using namespace std; int main() { int n = 0; cin>>n; while (n--) { string s; cin>>s; char cur = s[0]; string res = ""; res += cur; int state = 0; for (int i = 1; i < s.size(); i++) { if (state == 0) { res += s[i]; if (s[i] == cur) state = 1; else { cur = s[i]; continue; } } else if (state == 1) { if (s[i] == cur) continue; else { state = 2; res += s[i]; cur = s[i]; } } else if (state == 2) { if (cur == s[i]) continue; else { state = 0; cur = s[i]; res += s[i]; } } } cout<<res<<endl; } return 0; }
第二题:
这道题可以利用双指针来做,第一个指针指向A特工的位置,第二个指针去找A特工在该位置下另外两名特工的最远位置,利用组合数求解总次数后取模即可。
#include<string> #include<vector> #include<iostream> using namespace std; int main() { long long n = 0, dis = 0; cin>>n; cin>>dis; long long left = 0; long long right = 0; vector<int> buildings(n); long long res = 0; for (long i = 0; i < n; i++) cin >> buildings[i]; while (left < n - 2) { if (right < n && buildings[right] - buildings[left] <= dis) right ++; else { res += (right - left - 1)*(right - left - 2)/2; left ++; } } cout<<res%99997867; return 0; }
第三题:
这种游戏一般由于数据规模较小,可以利用回溯来暴力穷举可能,关键点在于每次都先加入第14张牌,然后再判断是否可行。
#include<string> #include<vector> #include<iostream> using namespace std; void dfs(vector<int>& result, unordered_map<int, int>& fly, unordered_map<int, int>& rest, int pos) { if (pos == 12) { return; } for (int i = 1; i <= 9; i++) { if (fly[i] >= 2) { fly[i] -= 2; dfs(result, fly, pos + 2); fly[i] += 2; } if (i <= 7 && fly[i] && fly[i+1] && fly[i+2]) { fly[i] --; fly[i+1] --; fly[i+2] --; dfs(result, fly, pos + 3); fly[i] ++; fly[i+1] ++; fly[i+2] ++; } } } int main() { unordered_map<int, int> fly; for (int i = 1; i <= 13; i ++) { int tmp = 0; cin>>tmp; fly[tmp] ++; } unordered_map<int, int> rest; for (int i = 1; i <= 9; i++) { rest[i] = 4 - fly[i]; } vector<int> result; dfs(1) return 0; }
第四题:
这道题可以采用的数据结构包括哈希表和map。
利用哈希表无法处理pair,因此题解采用了map,代码如下:
#include <iostream> #include <vector> #include <map> using namespace std; int main() { int n, m; cin >> n; int len; pair<int, int> xy; while (n--) { cin >> m; int maxCnt = 0; map<pair<int, int>, int> preFeaTimes; map<pair<int, int>, int> feaTimes; while (m--) { cin >> len; for (int i = 0; i < len; i++) { cin >> xy.first >> xy.second; if (preFeaTimes.count(xy)) feaTimes[xy] = preFeaTimes[xy] + 1; else feaTimes[xy] = 1; if (feaTimes[xy] > maxCnt) maxCnt = feaTimes[xy]; } preFeaTimes.clear(); preFeaTimes.swap(feaTimes); } cout << maxCnt << endl; } return 0; }
我的方法如下:
#include<iostream> #include<unordered_map> #include<vector> using namespace std; int check(vector<int>& seq) {//0 1 2 6 7 int tmp = -1; for (int i = 0; i < seq.size(); ) { int cur = i; while (cur < seq.size() - 1 && seq[cur + 1] - seq[cur] == 1) cur ++; tmp = max(tmp, cur - i + 1); if (i == cur) i ++; else i = cur; } return tmp; } int main() { int loop = 0; cin >> loop; while (loop --) { int frame = 0; cin >> frame; unordered_map<int, unordered_map<int, vector<int> > > map; for (int i = 0; i < frame; i++) { int sz = 0; cin >> sz; while (sz --) { int a, b; cin >> a; cin >> b; map[a][b].push_back(i); } } int resVal = -1; for (auto m:map) { for (auto n:m.second) { int cur = check(n.second); resVal = max(resVal, cur); } } cout<< resVal<<endl; } return 0; }
第五题:
旅行商问题,利用动态规划可以求解
状态设置得比较有意思,利用二进制得知识求解
#include<vector> #include<iostream> using namespace std; int helper(vector<vector<int>>& dis, vector<vector<int>>& dp, int city, int mode, int n) { if (dp[city][mode] != 20001) return dp[city][mode]; if (mode == ((1<<n) - 1)) return dis[city][0]; for (int i = 1, index = 0; i < (1<<n); i<<=1, index ++) {//一定要<<=而不是<< if ((mode | i) != mode) { dp[city][mode] = min(dp[city][mode], dis[city][index] + helper(dis, dp, index, (mode|i), n)); } } return dp[city][mode]; } int main() { int n = 0; cin >> n; vector<vector<int>> dis(n, vector<int> (n, 0)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) cin>>dis[i][j]; } int k = (1 << n) + 1; vector<vector<int>> dp(n, vector<int>(k, 20001)); cout<<helper(dis, dp, 0, 1, n); return 0; }
第六题:
传统的动态规划,找零钱问题
#include<iostream> #include<vector> using namespace std; int main() { int n = 0; cin>>n; int dp[1024 - n + 1]; dp[0] = 0; for (int i = 1; i <= 1024 - n; i++) { dp[i] = 2048; dp[i] = min(dp[i], dp[i - 1] + 1); if (i >= 4) dp[i] = min(dp[i], dp[i - 4] + 1); if (i >= 16) dp[i] = min(dp[i], dp[i - 16] + 1); if (i >= 64) dp[i] = min(dp[i], dp[i - 64] + 1); } cout<<dp[1024 - n]; return 0; }
第七题:
类似力扣地下城问题,要求反向dp
#include<iostream> #include<vector> using namespace std; int main() { int n = 0; cin>>n; vector<int> H(n); for(int i = 0; i < n; i++) cin>>H[i]; vector<int> dp(n + 1, 0); for (int i = n - 1; i >= 0; i --) dp[i] = (dp[i + 1] + H[i])/2; cout<<dp[0] + 1; return 0; }