微软好像是两面平行面,然后通过任意一轮可以进入leader面。一上午连续面了两面,说实话真有点吃不消,一面感觉还行,二面直接凉凉。
主要来说就是两道题,我都没见过,说实话非常慌,不过一面写出来了,二面思路对了但实现方面太紧张连在编辑器里加上using namespace std都忘了,被面试官吐槽,难受😫。其实这题我可以写出来的,越想越后悔,大概还是代码敲得太少,继续努力吧!下面复盘下面试过程。
题目
给出两行字符串,用空格分隔,第二行的称为前缀,查询第二行中每个前缀在第一行中出现的频率(简单来看就说是频数好了,反正除个n一样的)
举例
第一行:abc bcd abe
前缀:a ab bcd
那么前缀a在第一行中的单词出现了2次,ab出现了2次,bcd出现了一次。
想法1
对每个前缀,都在字符串中查找其出现的次数,复杂度是O(n*m)。(假设n为第一行单词个数,m为前缀个数)。
显然复杂度太高,而且n可能很大,前缀的长度也可能很长。继续优化。
想法2
将所有的前缀都存储在一个map里,遍历字符串,如果出现相应的前缀,将map里对应的计数+1。
还是被否定了,面试官说假设前缀非常多,大到map无法装到内存里。
然后在面试官的引导下,来到了最终的方法,利用树,来存储字符串(假设都是小写字母),加快查询的过程。
最终方法
我的想法是读入字符串,然后生成一个统计的树(后来我才意识到这是一种字典树),例如abc bcd abe,那么生成的树如下:
并且我想到在建立树的过程中,记录节点被访问的个数,那么查询的时候,比如ab,查询到a b时,计数为2,那么ab前缀出现了两次。事后我觉得我的方法甚至有那么一丝巧妙?可惜面试时太紧张,加上自定义数据结构非常生疏,没做出来。。。
ok看看最后的代码。时间复杂度为O(n+m*msize) n为字符串的个数,m为前缀个数,msize为前缀的长度。
代码
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
using namespace std;
struct Treenode {
vector<Treenode*> child;
int count;
Treenode() {
for (int i = 0; i < 26; i++) {
child.push_back(NULL);
}
count = 0;
}
};
vector<int> computePrefix(vector<string> strs, vector<string> prefix) {
Treenode* tree = new Treenode;
Treenode* cur;
for (int i = 0; i < strs.size(); i++) {
cur = tree;
for (int j = 0; j < strs[i].size(); j++) {
if (cur->child[strs[i][j]-'a'] == NULL) {
Treenode* next = new Treenode;
cur->child[strs[i][j] - 'a'] = next;
next->count++;
cur = next;
}
else {
cur = cur->child[strs[i][j] - 'a'];
cur->count++;
}
}
}
vector<int> res;
for (int i = 0; i < prefix.size(); i++) {
int cnt = 0;
int j;
cur = tree;
for (j = 0; j < prefix[i].size(); j++) {
if (cur->child[prefix[i][j]-'a'] != NULL) {
cur = cur->child[prefix[i][j]-'a'];
}
else {
break;
}
}
if (j == prefix[i].size()) {
cnt = cur->count;
}
res.push_back(cnt);
}
return res;
}
int main() {
vector<string> strs;
vector<string> prefix;
string str;
getline(cin, str);
istringstream is(str);
string tmp;
while (is >> tmp) {
strs.push_back(tmp);
}
getline(cin, str);
istringstream is2(str);
while (is2 >> tmp) {
prefix.push_back(tmp);
}
vector<int> res;
res=computePrefix(strs, prefix);
for (int i = 0; i < res.size(); i++) {
cout << res[i] << endl;
}
system("pause");
}
测试:
输入:abc ac bkd dk fdk f
a b ab d f fd
输出: