hw笔试题目解析(5.24)

华为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;
}

猜你喜欢

转载自blog.csdn.net/qq_43377917/article/details/130883330