本人报的机器学习工程师岗。2.5小时三道题。不知道为什么,机器学习工程师岗只考了代码……感觉和研发没区别……
第一题就是给一个日志,例如:
<diary><color=red>I am happy.<color=blue>I am sad.</color>I am happy.</color>This is black.</diary>
这个日志里的文字是有颜色的,(如果没有指定,则默认为black),然后统计每个有颜色的字符的个数。
#include<iostream>
#include<algorithm>
#include<stack>
#include<string>
#include<vector>
#include<unordered_map>
using namespace std;
string str_template = ".?!=+-()";
bool check(char i);
int main() {
int n;
cin >> n;
int case_ = 1;
while(n-- > 0) //n个测试样例
{
string buff;
getline(cin, buff); //输入日志
unordered_map<string, int> color; //采用哈希表统计每个颜色出现的字符个数
color["black"] = 0;
stack<string> color_stack; //用堆栈记录当前字符的颜色输出
color_stack.push("black");
int start = buff.find('<') + 7; //日志正式开始的位置
int end = buff.rfind('<'); //日志结束的位置
for(int i = start; i < end; i++)
{
if(buff[i] == '<')
{
if(buff[i+1] == 'c') //如果当前连续字符是"<c",则说明遇到了颜色起始标志<color=xxx>,则进行相应的统计
{
int j = i+7;
string temp = "";
while(buff[j] != '>')
{
temp += buff[j++];
}
if(color.find(temp) == color.end()) //如果这个颜色没出现过,则加入到哈希表中
color[temp] = 0;
color_stack.push(temp); //把当前的颜色压入栈
i = j; //i移动到相应的位置
}
else if(buff[i+1] == '/') //如果当前连续字符是"</",则说明遇到了颜色终止标志</color>
{
color_stack.pop(); //把当前颜色弹出栈
i += 7; //i移动到相应的位置
}
}
else if(check(buff[i])) //否则查看是不是合法的字符
color[color_stack.top()]++; //是的话,当前颜色的字符统计次数+1
}
cout << "Case " << case_++ << endl; //输出结果
for(auto it = color.begin(); it != color.end(); it++)
if(it->second > 0)
cout << it->first << ":" << it->second << endl;
}
return 0;
}
bool check(char i) {
return (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || (str_template.find(i) != str_template.size())
}
第二个题是,当前有32支队伍,分成8个小组A~G,每个小组头两名出线,然后进行16强的对阵抽签,其中必须满足以下四种条件:
(1) 同一地区的球队不对阵
(2) 各小组第一不对阵
(3) 各小组第二不对阵
(4) 同一组不对阵
问:有多少种抽签的情况。
-------------------------------------------------------
例子:
输入
A1 GZ
A2 HZ
B2 HZ
B1 GZ
...
H1 GZ
G1 GZ
G2 HZ
H2 HZ
输出:为相应的次数
从条件(2)(3)可以知道,我们可以把每个小组头第一名放到一个容器里,每个小组第二名放到另一个容器里。第一个容器的index为01234567,对应第index个小组,容器里只需要记录该队伍的地区就好。第二个容器为vector<pair<int, string>>,既记录相应的小组,也记录该队伍的地区。
那么现在问题就转换为,各个小组第一名 和 各个小组第二名 配对,会有多少种配对方式。这是一个全排列的问题。可以用回溯法来写。(顺便提一下,排列次数就是A(8 8)了,如果这个队伍数量太大的话,比如A(20 20)的话,这个计算量就爆炸了……这是个NP难问题,但还好,这个题里只是A(8 8),只要小于10都还好。)
全排列完了以后,可以进行条件(1)(4)的判断,如果符合这两个条件,则相应的统计次数+1即可。
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#define GROUP 8
using namespace std;
void sample(vector<string>& A, vector<pair<int, string>>& B, int num, int& count);
bool check(vector<string>& A, vector<pair<int, string>>& B);
int main() {
int n;
cin >> n;
vector<string> first(GROUP); //存放各小组第一名的地区
vector<pair<int, string>> second(GROUP); //存放第二名的队伍的小组编号和地区
while(n-- > 0)
{
int k = 0;
int TEAM = GROUP * 2;
for(int i = 0; i < TEAM; i++)
{
string buff1, buff2;
cin >> buff1;
cin >> buff2;
if(buff1[1] == '1')
first[buff1[0] - 'A'] = buff2;
else
second[k++] = make_pair(buff1[0] - 'A', buff2);
}
int count = 0;
sample(first, second, 0, count); //全排列
cout << count << endl;
}
return 0;
}
void sample(vector<string>& A, vector<pair<int, string>>& B, int num, int& count) {
if(num == GROUP)
{
if(check(A, B)) //check一下,是否满足条件(1)(4)
count++;
return;
}
else
{
for(int i = num; i < GROUP; i++)
{
swap(B[num], B[i]);
sample(A, B, num+1, count);
swap(B[num], B[i]);
}
}
}
bool check(vector<string>& A, vector<pair<int, string>>& B) {
for(int i = 0; i < GROUP; i++)
{
if(B[i].first == i || A[i] == B[i].second) //B的小组和A的小组不能一样,地区也不能一样
return false;
}
return true;
}
第三题好长……没来得及看题……主要是第一题的输入输出把我搞死了……线下可以输出,线上就是过不了……简直哭死。