华为5.24笔试题目全解析
1、华为笔试,连续空闲内存合并管理;
其实就是找最长的连续子串,并返回最小的下标值;
输入
输入:1,3,2,5 表示释放四块内存,ID分别为1.3.2.5,每块内存的大小为1个单位[预制条件]
函数执行前,所有内存均已被申请完毕,无空闲,不需考虑内存重复释放[取值范围]
内存ID编号:0<ID<2^31-1,单次释放的内存个数<10000
输出
输出:1,3 经过回收处理后,当前可用的最大连续内存大小3,以及此内存的起始编号1. 说明:1,3,2,5四块内存,前面三块1,3,2为连续内存,合并后的连续内存数为3个单位起始编号为1,因此返回1,3
代码分析:
#include <iostream>
#include <vector>
#include <algorithm>
#include<string>
using namespace std;
int main() {
vector<int> nums;
string input;
getline(cin, input);
//也可以这样去解析字符串
// for (char a : input)
// {
// if (a == ',')
// continue;
// else
// {
// int num = a - '0';
// nums.push_back(num);
// }
//
// }
size_t pos = 0;
string token;
while ((pos = input.find(",")) != string::npos) { //找不到返回npos
token = input.substr(0, pos);
nums.push_back(stoi(token));
input.erase(0, pos + 1); //删除从0开始的pos+1个字符
}
nums.push_back(stoi(input));
sort(nums.begin(), nums.end()); //升序排列
int st = -1, mxlen = -1;
int n = nums.size();
int index = 0;
while (index < n) {
int i = index;
for (int j = index + 1; j < n; j++) {
if (nums[j] - nums[i] != 1)
break;
i++;
}
//循环操作完之后更新最大值
if (mxlen < i - index + 1) {
mxlen = i - index + 1;
st = index;
}
index = i + 1; //下一波开始
}
cout << nums[st] << ", " << mxlen << endl;
return 0;
}
2、华为笔试,海量日志抑制
海量日志”定义: 10ms内(<10ms)打印2条相同日志 (包含第2条均需要被抑制),即:仅保留第一条或100ms内(<100ms)打印10条相似日志(去除数字后完全相同的两条日志认为是“相似”,包含第10条均需要被抑制),即:仅保留前9条。日志抑制的理解:被抑制的日志,不记录到日志文件中
输入
本用例的日志条数(最大不超过1000条) 时间截:日志打印内容
约束
1、时间戳单位是ms,用32位无符号+进制整数表示 2、用例保证后一条日志时间戳不小于前一条; 3、一条日志打打印只占一行,一条日志内容不超过1024 Bytes; 4、用例保证1s内(<1s),最多100条日志 5、数字均为正整数。
输出
时间戳:日志打印内容 输出需要除去被抑制的日志
代码分析:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <regex>
#include <string>
#include<sstream>
using namespace std;
int main() {
int n;
cin >> n;
cin.ignore(); //清除以回车结束的输入缓冲区的内容,
vector<pair<int, string>> records;
unordered_map<string, vector<pair<int, int>>> same;
unordered_map<string, vector<pair<int, int>>> like;
vector<bool> vst(n, true);
for (int i = 0; i < n; i++) { //i表示行数
string line;
getline(cin, line); //getline会丢弃换行符
istringstream iss(line); //字符串的输入流
// 有参构造,输入流 ,默认构造表示输入流的结束位置
//输入流迭代器,划分成一个个单词
//istream_iterator<string>默认以空白字符(包括空格、制表符、换行符等)作为分隔符来提取字符串
vector<string> lines(istream_iterator<string>{iss}, istream_iterator<string>()); //范围构造函数
int time = stoi(lines[0]); //哪怕后面有字母 也只会转换数字
//text是后面的字符串
string text = "";
for (int j = 1; j < lines.size(); j++) {
text += lines[j];
if (j != lines.size() - 1)
text += " ";
}
same[text].push_back(make_pair(time, i));
//\\d表示匹配任意数字字符,+表示匹配前面的元素一次或多次。
//regex_replace(text, regex("\\d+"), ""):这是一个使用正则表达式进行替换的函数调用
//将所有数字替换为空字符串,删掉数字
string likeText = regex_replace(text, regex("\\d+"), ""); //不喊时间和数字
like[likeText].push_back(make_pair(time, i));
records.push_back(make_pair(time, text)); //用来记录 所有的信息
}
//判断相同的日志
for (auto& d : same) {
vector<pair<int, int>>& record = d.second;
for (int i = 0; i < record.size(); i++) {
int time = record[i].first;
int index = record[i].second;
if (i + 1 < record.size() && record[i + 1].first - time < 10) //满足相同日志条件
vst[index + 1] = false;
}
}
//判断相似的日志
for (auto& d : like) {
vector<pair<int, int>>& record = d.second;
for (int i = 0; i + 9 < record.size(); i++) {
int time = record[i].first;
int index = record[i].second;
if (record[i + 9].first - time < 100)
vst[index + 9] = false;
}
}
for (int i = 0; i < records.size(); i++) {
if (vst[i])
cout << records[i].first << " : " << records[i].second << endl;
}
return 0;
}
3、华为笔试,网络升级改造
输入的网络是一个满二叉树结构,每个网络节点上标注一个数值,表示该节点的每年维护成本费用。给定每个输入网络,按照要求撤掉某些节点后,求出能够节省的最大的维护成本(这个题就类似二叉树的打家劫舍问题)
输入
第一行:一个正整数N,表示后面有N个数值。1<=N<= 10000 第二行:N个非负整数,表示网络节点每年的维护成本,按照满二又树的”广度优先遍历序号”给出。0表示不存在该关联节点,0只会存在于叶子节点上。每个数字的取值范围为[0.1000]
示例:
输入
第一行输入:7,表示后面有7个数字。
第二行输入:5 3 5 0 6 0 1,表示”表示网络节点每年的维护成本,按照满二叉树的“广度优先遍历序号”给出。0表示不存在该关联节点”
输出
能够节省的最大的维护成本。 12
按照二叉树的打家劫舍去做:
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<algorithm>
#include<unordered_map>
using namespace std;
struct TreeNode
{
int val;
TreeNode *left;
TreeNode * right;
TreeNode():val(0),left(nullptr),right(nullptr){}
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode * left, TreeNode* right) :val(x), left(left), right(right) {}
};
unordered_map<TreeNode*, int>memo;
int rob(TreeNode* root)
{
if (root == nullptr)
return 0;
if (memo.count(root))
return memo[root];
int do_it = root->val
+ (root->left == nullptr ? 0 : rob(root->left->left) + rob(root->left->right))
+ (root->right == nullptr ? 0 : rob(root->right->left) + rob(root->right->right));
int not_do = rob(root->left) + rob(root->right);
int res = max(do_it, not_do);
memo[root] = res;
return res;
}
TreeNode* buildtree(vector<int>& input) //根据层序遍历去构造二叉树
{
if (input.empty()) return nullptr;
TreeNode* root = new TreeNode(input[0]);
queue<TreeNode*>q;
q.push(root);
for (int i = 1; i < input.size();)
{
TreeNode* next_head = q.front();
q.pop();
int left = input[i++];
if (left != 0)
{
next_head->left = new TreeNode(left);
q.push(next_head->left);
}
else
{
next_head->left = nullptr;
}
int right = input[i++];
if (right != 0)
{
next_head->right = new TreeNode(right);
q.push(next_head->right);
}
else
{
next_head->right = nullptr;
}
}
return root;
}
int main()
{
vector<int>input;
int num;
cin >> num;
for(int i = 0; i < num; i++)
{
int a;
cin >> a;
input.push_back(a);
}
if (num == 1)
{
cout << input[0] << endl;
return 0;
}
TreeNode * root = buildtree(input);
int res = rob(root);
cout << res << endl;
system("pause");
return 0;
}
不构建二叉树,直接dfs:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int n;
vector<int> nums;
unordered_map<int, int> dp;
//node对应索引
int dfs(int node) {
if (node >= n) return 0;//>= 因为会*2
if (dp.count(node)) return dp[node];//类似备忘录
// Select
//在层序遍历的情况下,node*2+1对应这个节点的左子树,node*2+2对应右子树,再套一层*2+1就是左子树的下一个左子树
// 选择这个节点,这个节点的左子树和右子树不选择
int cur = dfs((node * 2 + 1) * 2 + 1) + dfs((node * 2 + 1) * 2 + 2) + dfs((node * 2 + 2) * 2 + 1) + dfs((node * 2 + 2) * 2 + 2) + nums[node];
// Don't select
cur = max(cur, dfs(node * 2 + 1) + dfs(node * 2 + 2));
dp[node] = cur;
return cur;
}
int main() {
cin >> n;
nums.resize(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
cout << dfs(0) << endl;
return 0;
}