華爲2020 暑期實習生 通用軟件開發工程師 筆試回憶

題型

  • 編程 3道 120分鐘

編程1:員工評選

投票選舉最佳員工,選出得票數最高的員工,若:
1)票數相同,按名字的字典序排序;
2)票數相同且名字有包含關係(Tom和Tomy),則名字短者在前。

  • 輸入:一行,名字之間用隔開,如:Tom,Lucy,Tom,Jack,Rose
  • 輸出:最佳員工的名字,如:Tom
  • 思路:設置結構體存儲名字和票數,創建一個結構體數組,然後調用sort函數傳一個lamda表達式進行排序,最後輸出第一個元素;
  • 參考代碼(AC 75%):
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<string>
#include<set>

using namespace std;

bool contain(string &s1, string &s2);

struct person{
	string name;
	int vote;
	person(string s, int v):name(s),vote(v){}
};

int main(){
	string str;
	cin >> str;
	vector<string> names;
	map<string, int> votes;
	int start = 0, end = 0;
	while (end != str.size())
	{
		if (str[end] == ',')
		{
			string name = str.substr(start, end - start);
			names.push_back(name);
			start = end + 1;
			end++;
		}
		else if (isalpha(str[end]))
			end++;
		else
        {
            cout << "error.0001";
            return 0;
        }
	}
	names.push_back(str.substr(start, end - start));
	for (auto &n : names)
		votes[n]++;
	vector<person> ps;
	for (auto v : votes)
		ps.push_back(person(v.first, v.second));
	sort(ps.begin(), ps.end(),
		[&votes](const person &p1, const person &p2){
		if (p1.vote != p2.vote)
			return p1.vote > p2.vote;
		else if (contain(p1.name, p2.name))
			return p1.name.size() < p2.name.size();
		else
			return p1.name < p2.name ;
	}
	);
	cout << ps[0].name;
	return 0;
}

bool contain(string &s1, string &s2)
{
	if (s1.size() < s2.size())
	{
		string temp = s2;
		s2 = s1;
		s1 = temp;
	}
	for (int i = 0; i<=s1.size() - s2.size(); i++)
	{
		if (s1[i] == s2[0])
        {
            bool tag = true;
            int j = 0;
            while(j < s2.size())
            {
                if(s1[i + j] != s2[j])
                {
                    tag = false;
                    break;
                }
                j++;
            }
            if(tag) return true;
        }
	}
	return false;
}

編程2:字符匹配

這道題題意看的不是很懂。
給出一個待匹配串,一個表示若干寄存器的固定格式的母串,寄存器格式:xxx[name:xxx,mask:xxx,val:xxx],母串有多個寄存器字符串通過相連,匹配規則:1)待匹配串和寄存器編號相同;2)待匹配串的name、mask、val和母串中的某個寄存器相同。

  • 輸入:待匹配串,母串,空格相隔;
  • 輸出:對於每一個匹配到的寄存器,輸出寄存器的name mask val空格相隔;
  • 思路:這道題最後沒時間了(代碼裏有大量的if/else沒來得及優化),就只考慮了待匹配串是一個寄存器編號的情況。設置下標start和end遍歷母串,不斷截取需要的字符串進行比較或者輸出就行。
  • 參考代碼(AC 75%):
#include<iostream>
#include<string>
#include<algorithm>

using namespace std;

int main(){
	string str, sta;
	cin >> str >> sta;
	string temp;
	int start = 0, end = 0;
	while (end != sta.size())
	{
		if (sta[end] == '[')
		{
			string s = sta.substr(start, end - start);
			start = end + 1;
			end++;
			if (str == s)
			{
				while (sta[end] != ']')
				{
					if (sta[end] == '=')
					{
						start = end + 1;
						end++;
					}
					else if (sta[end] == ',')
					{
						string s = sta.substr(start, end - start);
						cout << s << " ";
						start = end + 1;
						end++;
					}
					else
						end++;
				}
				string s = sta.substr(start, end - start);
				cout << s << " ";
				cout << endl;
			}
		}
		else if (sta[end] == ',')
		{
			start = end + 1;
			end++;
		}
		else
			end++;
	}
	return 0;
}

編程3:最長調用鏈

給出n個函數,每個函數的權值,以及每個函數可以調用的其他函數,輸出權值最大的調用鏈的權值。

  • 輸入:第一行,x a b c d ...x代表函數的個數,後邊的x個數代表每個函數可以調用的其他函數個數;
    接下來x行,每行如z y a b c ...z代表函數編號,y代表函數權值,後面的若干數代表函數x可以調用的函數編號;
  • 輸出:最大權值;
  • 思路:記憶遞歸,但是提示段錯誤:可能數組越界或者遞歸深度過大,之前沒記憶化的時候也是這個提示,而且AC率沒有變;
  • 參考代碼(AC 60%):
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>

using namespace std;

int maxval = 0;
map<int, int> cache;

int calcu(vector<vector<int>> &call, set<int> &memo, int index, vector<int> &val, int curr);

int main(){
	int n;
	cin >> n;
	vector<int> temp(n + 1);
	for (int i = 1; i <= n; i++)
		cin >> temp[i];
	vector<vector<int>> call(n + 1);
	vector<int> val(n + 1);
	for (int i = 1; i <= n; i++)
	{
		int x, v;
		cin >> x >> v;
		val[x] = v;
		for (int j = 0; j<temp[i]; j++)
		{
			int x;
			cin >> x;
			call[i].push_back(x);
		}
	}
	for (int i = 1; i <= n; i++)
	{
		if (temp[i] != 0)
		{
			set<int> memo;
			if (calcu(call, memo, i, val, 0) == -1)
			{
				cout << "R";
				return 0;
			}
		}
	}
	cout << maxval;
	return 0;
}

int calcu(vector<vector<int>> &call, set<int> &memo, int index, vector<int> &val, int curr)
{
	if (memo.count(index))
	{
		return -1;
	}
	if (cache.count(index))
	{
		curr += cache[index];
		maxval = max(maxval, curr);
		return curr;
	}
	curr += val[index];
	memo.insert(index);
	if (call[index].size() == 0)
	{
		maxval = max(maxval, curr);
		return curr;
	}
	for (auto v : call[index])
	{
		int temp = calcu(call, memo, v, val, curr);
		if (temp == -1)
			return -1;
		cache[index] = max(cache[index], temp - curr);
		memo.erase(v);
	}
	//no use
	return curr;
}

華爲的筆試題還是有一定難度的,而且輸入的處理真的很讓人腦闊疼,感覺自己一直在截字符串233,不過總的來說邏輯清晰的話還是能AC一部分(留下了羞愧的淚水)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章