前排先说一下,根据个人经验,笔试基本上只要能过线就行,对后续流程影响真的不大。
我已经不知道有多少家公司,笔试题全A,然后简历被刷,或是一面后被刷了。
我腾讯的流程其实已经结束了。
所以诸位不用对笔试成绩过分看重。
奇怪了,我发布时代码选的是C++,发出来变成plain text了
腾子这次笔试题难度还是不太大的,比美团难一些,不过肯定比米哈游网易雷火这种笔试简单的多。
1、对k个链表进行排序。
思路:初看以为是k个升序链表(样例是升序),仔细一看题目描述链表是乱序的,所以直接摧毁原始链表,提取所有数值并排序,最后用排序好的数值重新建一个链表即可,没必要在链表上进行操作。
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 返回一个指向链表头部的指针。 * @param a ListNode类vector 指向这些数链的开头 * @return ListNode类 */ ListNode* solve(vector<ListNode*>& a) { vector<int> nums; for (auto& head : a) { while (head != nullptr) { nums.emplace_back(head->val); auto node_next = head->next; delete(head); head = node_next; } } sort(nums.begin(), nums.end(), [](int a, int b) {return a < b; }); ListNode* head = new ListNode(nums[0]); ListNode* tmp_node = head; for (int i = 1; i < nums.size(); i++) { tmp_node->next = new ListNode(nums[i]); tmp_node = tmp_node->next; } return head; } };
2、对一个正整数数组中的数字执行k次操作,求k次操作后数组和的最小值。对数字的操作如下:
如果x是偶数,则操作后x = 2*x + 1
如果x是奇数,则操作后x = 2*x
思路:简单贪心即可,每次操作最小的那个数字即可。用优先队列更好,但是忘了如何规定优先队列升序还是降序,所以用了map
#include<iostream> #include<map> using namespace std; int main() { int n, k; cin >> n >> k; long long sum = 0; map<long long, int> nums; for (int i = 0; i < n; i++) { long long num; cin >> num; nums[num]++; sum += num; } for (int i = 0; i < k; i++) { auto it = nums.begin(); long long num = it->first; sum -= num; if (num % 2 == 0) num = num * 2 + 1; else num = num * 2; it->second--; if (it->second == 0)nums.erase(it); nums[num]++; sum += num; } cout << sum << endl; return 0; }
3、有n辆赛车,以及所有赛车的当前位置p,速度v,假设赛车均做匀速直线运动。问你t时刻后,有多少赛车的名次发生了改变?
思路:初始输入是有序的,只用对t时刻后的位置重新排序重新计算名次即可。
#include<iostream> #include<vector> #include<algorithm> using namespace std; struct car { int pos = 0; int rank_now = 0; int rank_new = 0; }; int main() { int n, t; cin >> n >> t; vector<car> cars(n); for (int i = 0; i < n; i++) { cin >> cars[n - 1 - i].pos; } cars[0].rank_now = 1; for (int i = 1; i < n; i++) { if (cars[i].pos == cars[i - 1].pos) cars[i].rank_now = cars[i - 1].rank_now; else cars[i].rank_now = i + 1; } for (int i = 0; i < n; i++) { int v; cin >> v; cars[n - 1 - i].pos += v * t; } sort(cars.begin(), cars.end(), [](car a, car b) {return a.pos > b.pos; }); int count = 0; cars[0].rank_new = 1; if (cars[0].rank_now > cars[0].rank_new)count++; for (int i = 1; i < n; i++) { if (cars[i].pos == cars[i - 1].pos) cars[i].rank_new = cars[i - 1].rank_new; else cars[i].rank_new = i + 1; if (cars[i].rank_now > cars[i].rank_new) count++; } cout << count << endl; return 0; }
4、对于一个字符串,将其首字符放在末尾,这个操作称为旋转字符串("abcdef" -> "bcdefa") 。对于两个字符串,如果其中一个字符串可以通过一次或多次旋转变成另一个字符串,则这两个字符串“互旋”
给你T组数据,问你每组数据中是否存在两个字符串“互旋”?
思路:观察数据量,字符串数量很多,字符串长度不长,如果两两比较肯定超时,应当用哈希表匹配。
#include<iostream> #include<string> #include<unordered_set> using namespace std; int main() { int T; cin >> T; for (int i = 0; i < T; i++) { int n; cin >> n; bool isFind = false; unordered_set<string> strs; for (int j = 0; j < n; j++) { string str; cin >> str; if (isFind)continue; for (int k = 0; k < str.length(); k++) { std::rotate(str.begin(), str.begin() + str.length() - 1, str.end()); if (strs.find(str) != strs.end()) { isFind = true; break; } } if (!isFind) strs.insert(str); } if (isFind) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
5、有n个数字,数字可能为0可能为1,告诉你每个数字的坐标值。你可以将k个1变为0。
你每次操作可以让一个0的位置+1或是-1,。
问你最少需要几次操作使得所有0之间没有1。(如果0和1重合,视为中间有1)
思路:对于所有1
计算将1左侧所有0移动到1右侧的操作数(表示将所有0移动到这个1右侧需要的代价lcost)
计算将1右侧所有0移动到1左侧的操作数(表示将所有0移动到这个1左侧需要的代价rcost)
在所有数字左侧添加一个1,其左代价lcost = 0;在所有数字右侧添加一个1,其右代价rcost = 0;
那么,对于两个1,左侧的1的lcost和右侧的1的rcost加起来,即是将所有0移动到这两个1之间所需要的操作数。
遍历所有1,求lcost[i] 与rcost[i + k + 1](因为可以将中间k个1变为0,所以右侧选i + k + 1)的最小值即可
#include<iostream> #include<vector> using namespace std; int main() { int n, k; cin >> n >> k; vector<long long> pos(n); vector<int> color(n); vector<int> blue_idx; for (int i = 0; i < n; i++) { cin >> pos[i]; } for (int i = 0; i < n; i++) { cin >> color[i]; if (color[i] == 1) { blue_idx.emplace_back(i); } } int num_blue = blue_idx.size(); vector<long long> lcost(num_blue + 2, 0); vector<long long> rcost(num_blue + 2, 0); int lnum = 0; long long lpos = 0; long long lidx = -1; for (int i = 0; i < num_blue; i++) { long long pos_now = pos[blue_idx[i]]; lcost[i + 1] = lcost[i] + (pos_now - lpos) * lnum; for (int p = lidx + 1; p < blue_idx[i]; p++) { lcost[i + 1] += pos_now - pos[p] + 1; lnum++; } lpos = pos_now; lidx = blue_idx[i]; } int rnum = 0; long long rpos = pos[n - 1]; long long ridx = n; for (int i = num_blue; i > 0; i--) { long long pos_now = pos[blue_idx[i - 1]]; rcost[i] = rcost[i + 1] + (rpos - pos_now) * rnum; for (int p = ridx - 1; p > blue_idx[i - 1]; p--) { rcost[i] += pos[p] - pos_now + 1; rnum++; } rpos = pos_now; ridx = blue_idx[i - 1]; } long long cost_min = lcost[num_blue]; for (int i = 0, j = k + 1; j <= num_blue + 1; i++, j++) { long long cost_now = lcost[i] + rcost[j]; if (cost_now < cost_min) cost_min = cost_now; //if (cost_now == 0) //{ // int p = j - 1; // while (p > i && lcost[i] + rcost[p] == 0)p--; // if (cost_min > p - i) // cost_min = p - i; //} //else //{ // int p = j - 1; // while (p > i && lcost[i] + rcost[p] == cost_now)p--; // if (cost_min > cost_now + p - i) // cost_min = cost_now + p - i; //} } cout << cost_min << endl; return 0; }